【问题标题】:curl : send html email with embedded image and attachmentcurl :发送带有嵌入图像和附件的 html 电子邮件
【发布时间】:2017-06-23 19:41:09
【问题描述】:

我的目标是使用 curl 发送一封带有嵌入图像的 html 正文的电子邮件,例如:

我正在发送这样的电子邮件:

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

我的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

解码出来的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>

如何在这个 html 中嵌入 admin.png 并附加另一个文件 log.txt 使用curlbash 发送到此电子邮件?

【问题讨论】:

    标签: bash email curl smtp


    【解决方案1】:

    我想出的解决方案是将所有附件(图像和文本文件)进行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--
    

    Content-Id 标头用于标识可以在 html 中引用的资源:@​​987654325@ like :

    <img src="cid:admin.png" width="150" height="50">
    

    这是一个完整的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
    

    【讨论】:

    • 您的代码示例有点误导,实际上它不起作用。正如您所说,您只需将每个部分包含在边界“--MULTIPART-MIXED-BOUNDARY”中。
    • @DanielJ。我刚刚测试了上面的脚本,它对我有用。如果您使用gmail帐户发送电子邮件,则需要在google设置中允许安全性较低的应用程序,不确定您遇到了什么错误
    • 我可能是错的,或者 bash 解释器或 curl 版本可能存在一些差异。无论如何代码都是多余的,你不需要嵌套边界。
    【解决方案2】:

    另外,您的代码示例有点误导,实际上它不起作用。 正如您所说,您只需将每个部分都包含在一个边界中,在您的情况下,分隔符是:

    “--多部分混合边界”。

    尽管如此,它也可以是任何其他用户定义的字符串。 您正在嵌套多个边界类型,这不是必需的。 HTML 内容不需要进行 base64 编码,如果您愿意,也可以对其进行编码。

    每个分隔符前后都需要一个空行。

    我建议看一下 W3 论文和示例:https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html

    【讨论】:

      【解决方案3】:

      这是一个您可以使用的 shell 脚本。 我大量来源于https://blog.ambor.com/2021/08/using-curl-to-send-e-mail-with.html

      密码可以存储在 .netrc 文件中,如下所述:https://everything.curl.dev/usingcurl/netrc,但我没有尝试过。

      只需确保您需要的图像使用 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
      

      【讨论】:

        猜你喜欢
        • 2012-04-07
        • 2011-04-16
        • 2021-10-31
        • 2013-11-26
        • 2012-07-29
        • 2011-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多