I am converting a shell script to python. In my python code , when i tried to send email , i am getting error message.I am new to python. Please help me on solving this.
Shell code:
id=`whoami`
userid_list=2nd_user
SUBJECT=mail
echo "Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 7bit
From: $id
To: $userid_list
Subject: $SUBJECT
" > $email
SENDMAIL=/usr/lib/sendmail
$SENDMAIL -oi -t < $email
python code :
sender_id = getpass.getuser()
userid = getpass.getuser()
content = """Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 7bit
From: """ + sender__id + """
To: """ + userid + """
Subject: mail"""
email= "/tmp/mail"
with open(email, 'a') as f:
f.write(content)
SENDMAIL = "/usr/lib/sendmail"
subprocess.call(SENDMAIL + " -oi -t < " + email, shell=True)
Error message:
sendmail: fatal: vijay(1254164854): No recipient addresses found in message header
The sender__id in your content variable has two underscores instead of the original declared sender_id which only has one.
Python treats each variable as an object and each variable doesn't need to be declared for it to be used, so the compiler/interpreter will not warn you if it encounters situations such as the one you posted.
Line alignment of two mail files(1 from shell & 1 form python) are different.When i changed the alignment, it worked.
email file from shell:
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 7bit
From: vijay
To: kumar
Subject: test mail
email file("/tmp/mail") from python:
Content-Type: text/html; charset=iso-8859-1
Content-Transfer-Encoding: 7bit
From: vijay
To: kumar
Subject: test mail
I changed the alignment of email file(generated from python code) as shell.It worked
Related
I wish to have a portable Unix way of programmatically sending an e-mail with an attachment. The "standard" Unix way of sending an e-mail seems to be mail(1), but there seems to be no portable way of specifying an attachment. (Yes, I know that some versions of mail(1) have an -a or an -A option, but that's not standard, so I cannot rely on it.)
I'll be using ruby for this, but I want a generic solution, i.e., a special ruby configuration involving (say) using Net::SMTP and specifying details like the SMTP server &c. should not be in the application, but the application should issue a command like mail <some other stuff here> and from there the system should deliver the mail (with a suitable ~/.mailrc or whatever).
mail command will work only if it can find a SMTP host. There is a number of ways it can be done (sSMTP, Postfix, sendmail). The most "normal" way is to have sendmail running on your computer, which means localhost itself is an SMTP server. I don't know of a way of getting the SMTP configuration automatically if you don't have sendmail installed.
Therefore, assuming you know the SMTP server (localhost in this example), from Tutorials Point a pure Ruby mail attachment:
require 'net/smtp'
filename = "/tmp/test.txt"
# Read a file and encode it into base64 format
filecontent = File.read(filename)
encodedcontent = [filecontent].pack("m") # base64
marker = "AUNIQUEMARKER"
body = <<EOF
This is a test email to send an attachement.
EOF
# Define the main headers.
part1 = <<EOF
From: Private Person <me#fromdomain.net>
To: A Test User <test#todmain.com>
Subject: Sending Attachement
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary = #{marker}
--#{marker}
EOF
# Define the message action
part2 = <<EOF
Content-Type: text/plain
Content-Transfer-Encoding:8bit
#{body}
--#{marker}
EOF
# Define the attachment section
part3 = <<EOF
Content-Type: multipart/mixed; name = \"#{filename}\"
Content-Transfer-Encoding:base64
Content-Disposition: attachment; filename = "#{filename}"
#{encodedcontent}
--#{marker}--
EOF
mailtext = part1 + part2 + part3
# Let's put our code in safe area
begin
Net::SMTP.start('localhost') do |smtp|
smtp.sendmail(mailtext, 'me#fromdomain.net', ['test#todmain.com'])
end
rescue Exception => e
print "Exception occured: " + e
end
My goal is to send an email using curl with an html body with embedded image such as :
I'm sending the email like this :
curl "smtp://smtp.gmail.com:587" -v \
--mail-from "sender#gmail.com" \
--mail-rcpt "receiver#gmail.com" \
--ssl -u sender#gmail.com:secretpassword \
-T "message.txt" -k --anyauth
My message.txt looks like :
From: Some Name <sender#gmail.com>
To: Some Name <receiver#gmail.com>
Subject: example of mail
Reply-To: Some Name <sender#gmail.com>
Cc:
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="MULTIPART-MIXED-BOUNDARY"
--MULTIPART-MIXED-BOUNDARY
Content-Type: multipart/alternative; boundary="MULTIPART-ALTERNATIVE-BOUNDARY"
--MULTIPART-ALTERNATIVE-BOUNDARY
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: base64
Content-Disposition: inline
PGh0bWw+Cjxib2R5PgogICAgPGRpdj4KICAgICAgICA8cD5IZWxsbywgPC9wPgogICAgICAgIDxw
PlBsZWFzZSBzZWUgdGhlIGxvZyBmaWxlIGF0dGFjaGVkPC9wPgogICAgICAgIDxwPkFkbWluIFRl
YW08L3A+CiAgICAgICAgPGltZyBzcmM9ImFkbWluLnBuZyIgd2lkdGg9IjE1MCIgaGVpZ2h0PSI1
MCI+CiAgICA8L2Rpdj4KPC9ib2R5Pgo8L2h0bWw+Cg==
--MULTIPART-ALTERNATIVE-BOUNDARY--
--MULTIPART-MIXED-BOUNDARY
The html decoded is :
<html>
<body>
<div>
<p>Hello, </p>
<p>Please see the log file attached</p>
<p>Admin Team</p>
<img src="admin.png" width="150" height="50">
</div>
</body>
</html>
How can I embed admin.png in this html and attach another file log.txt
to this email using curl and bash ?
The solution I came up with is to base64 encode all the attachment (image and text file) and to include them into the uploaded file directly in the multipart/mixed body such as :
--MULTIPART-MIXED-BOUNDARY
Content-Type: image/png
Content-Transfer-Encoding: base64
Content-Disposition: inline
Content-Id: <admin.png>
iVBORw0KGgoAAAANSUhEUgAAAIAAAACgCAIAAABL8POqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA
B3RJTUUH4AQNDwEVouBdqAAAG2xJREFUeNrtfX9oHFe25jdDBU5BG25BG7pABhXEkDJjSIsYIs1m
WbfJA8ubhcjjgdiTQNJOYCInj0RKYGIl8CbyPF4iZSCxEkgsB5LIgWQlL2Pcfow3bdgw0mMzox6e
....
--MULTIPART-MIXED-BOUNDARY
Content-Type: text/plain
Content-Transfer-Encoding: base64
Content-Disposition: inline; filename=log.txt
c29tZSBsb2cgaW4gYSB0eHQgZmlsZSB0byBhdHRhY2ggdG8gdGhlIG1haWwK
--MULTIPART-MIXED-BOUNDARY--
The Content-Id header is used to identify the resource that can be referenced in the html with : cid: like :
<img src="cid:admin.png" width="150" height="50">
Here is a complete bash example to send an html email with and admin.png embedded image and a log.txt attached to it :
#!/bin/bash
rtmp_url="smtp://smtp.gmail.com:587"
rtmp_from="sender#gmail.com"
rtmp_to="receiver#gmail.com"
rtmp_credentials="sender#gmail.com:secretpassword"
file_upload="data.txt"
# html message to send
echo "<html>
<body>
<div>
<p>Hello, </p>
<p>Please see the log file attached</p>
<p>Admin Team</p>
<img src=\"cid:admin.png\" width=\"150\" height=\"50\">
</div>
</body>
</html>" > message.html
# log.txt file to attached to the mail
echo "some log in a txt file to attach to the mail" > log.txt
mail_from="Some Name <$rtmp_from>"
mail_to="Some Name <$rtmp_to>"
mail_subject="example of mail"
mail_reply_to="Some Name <$rtmp_from>"
mail_cc=""
# add an image to data.txt :
# $1 : type (ex : image/png)
# $2 : image content id filename (match the cid:filename.png in html document)
# $3 : image content base64 encoded
# $4 : filename for the attached file if content id filename empty
function add_file {
echo "--MULTIPART-MIXED-BOUNDARY
Content-Type: $1
Content-Transfer-Encoding: base64" >> "$file_upload"
if [ ! -z "$2" ]; then
echo "Content-Disposition: inline
Content-Id: <$2>" >> "$file_upload"
else
echo "Content-Disposition: attachment; filename=$4" >> "$file_upload"
fi
echo "$3
" >> "$file_upload"
}
message_base64=$(cat message.html | base64)
echo "From: $mail_from
To: $mail_to
Subject: $mail_subject
Reply-To: $mail_reply_to
Cc: $mail_cc
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=\"MULTIPART-MIXED-BOUNDARY\"
--MULTIPART-MIXED-BOUNDARY
Content-Type: multipart/alternative; boundary=\"MULTIPART-ALTERNATIVE-BOUNDARY\"
--MULTIPART-ALTERNATIVE-BOUNDARY
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: base64
Content-Disposition: inline
$message_base64
--MULTIPART-ALTERNATIVE-BOUNDARY--" > "$file_upload"
# add an image with corresponding content-id (here admin.png)
image_base64=$(curl -s "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_116x41dp.png" | base64)
add_file "image/png" "admin.png" "$image_base64"
# add the log file
log_file=$(cat log.txt | base64)
add_file "text/plain" "" "$log_file" "log.txt"
# add another image
#image_base64=$(curl -s "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_116x41dp.png" | base64)
#add_file "image/png" "something.png" "$image_base64"
# end of uploaded file
echo "--MULTIPART-MIXED-BOUNDARY--" >> "$file_upload"
# send email
echo "sending ...."
curl -s "$rtmp_url" \
--mail-from "$rtmp_from" \
--mail-rcpt "$rtmp_to" \
--ssl -u "$rtmp_credentials" \
-T "$file_upload" -k --anyauth
res=$?
if test "$res" != "0"; then
echo "sending failed with: $res"
else
echo "OK"
fi
Here's a shell script you could use.
I heavily derived from https://blog.ambor.com/2021/08/using-curl-to-send-e-mail-with.html
Passwords could be stored in a .netrc file as discussed on: https://everything.curl.dev/usingcurl/netrc but I haven't tried that.
Just make sure the image you need is embedded in the HTML using base64 encoding.
#!/bin/bash
declare -a VOPTS;
declare -a HOPTS;
sesAccess="sender.account.authentication#email.id" ;
sesSecret="sender.account.passwordXXXXXX";
sesFromName="Sender Full Name";
sesFromAddress='<sender#email.id>';
sesToName="Recipient Full Name";
sesToAddress="<recepient#email.id>"
sesSubject="Email Subject Line";
sesSMTP='mail.server.fqdn';
sesPort='465';
sesMessage=$'Test of line 1\nTest of line 2'
sesFile="$1"; # attachment is first argument
sesHTMLbody="/path/to/html/file.html"; # content of this file will be used to create HTML body
sesMIMEType=`file --mime-type "$sesFile" | sed 's/.*: //'`;
# sesMIMEType=`file -b --mime-type "$sesFile"`;
VOPTS=();
HOPTS=();
#Curl Options
VOPTS+=("-v");
VOPTS+=("--url"); VOPTS+=("smtps://$sesSMTP:$sesPort");
VOPTS+=("--ssl-reqd")
VOPTS+=("--user"); VOPTS+=("${sesAccess}:${sesSecret}");
VOPTS+=("--mail-from"); VOPTS+=("${sesFromAddress}");
VOPTS+=("--mail-rcpt"); VOPTS+=("${sesToAddress}");
#Header Options
HOPTS+=("-H"); HOPTS+=("Subject: ${sesSubject}");
HOPTS+=("-H"); HOPTS+=("From: ${sesFromName} ${sesFromAddress}");
HOPTS+=("-H"); HOPTS+=("To: ${sesToName} ${sesToAddress}");
curl "${VOPTS[#]}" -F '=(;type=multipart/mixed' -F "=<$sesHTMLbody;type=text/html;encoder=base64" -F "file=#$sesFile;type=$sesMIMEType;encoder=base64" -F '=)' "${HOPTS[#]}"
exit
Plus one, your code example is a bit misleading tough, in fact it doesn't work.
As you say, you just have to enclose each part in a boundary, in your case the delimiter is:
"--MULTIPART-MIXED-BOUNDARY".
Nonetheless it could be any other user defined string.
You are nesting multiple boundary types, which isn't necessary. HTML content doesn't need to be base64 encoded, it can go encoded if you will though.
You need a blank line after and before each delimiter.
I recommend taking a look at the W3 papers and examples: https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
The answer by #bertrand-martel was mostly right on my system running Ubuntu 22.04 and submitting to a postfix server in my network. The html email message came through just fine, and I had empty attachments named correctly. I had to edit the add_file function he defined and add in a blank line before the $3 at the very end. The email would not work without a blank line between the Content-Disposition: and the base64 encoding. I also had to insert a blank line after the --MULTIPART-ALTERNATIVE-BOUNDARY--
. Once I made those changes, the html message, the embedded image, and the attached file all came across correctly.
I would like to use curl to send an HTTP POST request with a multipart body, which consists of two parts part1 and part2 like this:
Content-Type: multipart/form-data;
boundary=v6jSBESHUN0nHdfaw-GnE4zGVcg0OLfL1
--v6jSBESHUN0nHdfaw-GnE4zGVcg0OLfL1
Content-Disposition: form-data; name="part1"
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 8bit
abc
--v6jSBESHUN0nHdfaw-GnE4zGVcg0OLfL1
Content-Disposition: form-data; name="part2"
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
xyz
--v6jSBESHUN0nHdfaw-GnE4zGVcg0OLfL1--
Note that the content of part1 is abc and the content of part2 is xyz. The charset of part1 is ascii and the charset of part2 is utf-8.
I am trying to do it as follows:
curl -X POST -F "part1=abc" -F "part2=xyx" http://myhost/mypost
Unfortunately it did not do the trick. Besides, I did not find to how specify the charset of part2. How would you suggest send this request with curl ?
You can set the type with ;type=
curl -X POST -F "part1=abc" -F "part2=xyx;type=text/plain; charset=utf-8" http://myhost/mypost
I understood how I can send a HTML message with sendmail doing:
(
echo "From: me#example.com";
echo "To: you#example.com";
echo "Subject: this is my subject";
echo "Content-Type: text/html";
echo "MIME-Version: 1.0";
echo "";
echo "My <b>HTML message<\b> goes here!";
) | sendmail -t
I also manages to send an attachement with mail doing
uuencode file.pdf file.pdf | mail -s "my subject" you#example.com
but I fail to send an HTML message with an attachement (.pdf).
Note that I failed to install mutt or mpack (using homebrew) so far so I would love a solution that works with mail, mailx or sendmail. I am on Mac OS X 10.11
What you need to do is use multipart mime.
Your Content-Type should be something like:
Content-Type: multipart/mixed; boundary=multipart-boundary
Your multipart-boundary can be any string you like.
Then you output a line "--multipart-boundary" followed by headers, then body for each part.
For example:
--multipart-boundary
Content-Type: text/html
My <b>HTML message<\b> goes here!
--multipart-boundary
Content-Type: application/pdf
Content-Disposition: attachment; filename=file.pdf
Content-Transfer-Encoding: base64
**cat your base64 encoded file here **
--multipart-boundary--
The extra two dashes at the end mark the end of last part. You can add as many attachments as you like.
I have the function below which uses the mail.
How do I add cc or bcc in it?
Doing this do not work: cat << EOF | mail ${CONTACT_EMAIL} -b email#email.com.br...
function SendMail () {
# Getting e-mails body text
TEXT=$(cat ${LOG_DIR}/${PROCESS_ID}.log)
cat << EOF | mail ${CONTACT_EMAIL}
From: ${MAIL_FROM}
Subject: X
To: X}
Cc: Leandro.Takeda#teste.com
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="-q1w2e3r4t5"
---q1w2e3r4t5
Content-Type: text/html
Content-Disposition: inline
X
EOF
}
man mail on my comp suggests -b a,b,c should go before to-address(es).
mail -b email#email.com.br ${CONTACT_EMAIL}
You may use sendmail program directly without mail program help.
SENDMAIL=/usr/sbin/sendmail
${SENDMAIL} -i -- ${CONTACT_EMAIL} Leandro.Takeda#teste.com jd#example.net <<EOF
From: ${MAIL_FROM}
Subject: X
To: ${CONTACT_EMAIL}
Cc: Leandro.Takeda#teste.com
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="-q1w2e3r4t5"
---q1w2e3r4t5
Content-Type: text/html
Content-Disposition: inline
X
EOF