[英]curl : send html email with embedded image and attachment
My goal is to send an email using curl
with an html body with embedded image such as:我的目标是使用curl
和带有嵌入图像的 html 主体发送 email,例如:
I'm sending the email like this:我像这样发送 email:
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:我的message.txt
看起来像:
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 为:
<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
? 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 :我想出的解决方案是对所有附件(图像和文本文件)进行 base64 编码,并将它们直接包含在multipart/mixed
正文中的上传文件中,例如:
--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 : Content-Id
标头用于标识可以在 html 中引用的资源: 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 :这是一个完整的bash
示例,用于发送带有admin.png
嵌入图像和log.txt
的 html 电子邮件:
#!/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
really want to follow up on your old post Scrap articles form wsj by requests, CURL and BeautifulSoup . 我真的很想通过请求,CURL和BeautifulSoup来跟踪您以前的旧报废表单wsj中的文章 。 is it possible to ask you to update the answer? 是否可以要求您更新答案? really appreciate it. 非常感谢。 has been working on it for many hours but could not figure out how to do it. 已经研究了许多小时,但无法弄清楚该怎么做。
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". “--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. HTML 内容不需要是 base64 编码的,如果你愿意,它可以被编码。
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我建议查看 W3 论文和示例: https : //www.w3.org/Protocols/rfc1341/7_2_Multipart.html
Here's a shell script you could use.这是您可以使用的 shell 脚本。 I heavily derived from https://blog.ambor.com/2021/08/using-curl-to-send-e-mail-with.html我大量来自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.密码可以存储在 .netrc 文件中,如下所述: https ://everything.curl.dev/usingcurl/netrc 但我没有尝试过。
Just make sure the image you need is embedded in the HTML using base64 encoding.只需确保您需要的图像使用 base64 编码嵌入到 HTML 中。
#!/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
The answer by @bertrand-martel was mostly right on my system running Ubuntu 22.04 and submitting to a postfix server in my network. @bertrand-martel 的答案在我运行 Ubuntu 22.04 并提交到我网络中的后缀服务器的系统上大部分是正确的。 The html email message came through just fine, and I had empty attachments named correctly. html email 消息通过就好了,我有正确命名的空附件。 I had to edit the add_file function he defined and add in a blank line before the $3 at the very end.我必须编辑他定义的 add_file function 并在最后的 $3 之前添加一个空行。 The email would not work without a blank line between the Content-Disposition: and the base64 encoding.如果 Content-Disposition: 和 base64 编码之间没有空行,email 将无法工作。 I also had to insert a blank line after the --MULTIPART-ALTERNATIVE-BOUNDARY--.我还必须在 --MULTIPART-ALTERNATIVE-BOUNDARY-- 之后插入一个空行。 Once I made those changes, the html message, the embedded image, and the attached file all came across correctly.一旦我进行了这些更改,html 消息、嵌入的图像和附件都正确出现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.