AWS SES SDK可以用于发送带附件的电子邮件。

huangapple go评论102阅读模式
英文:

AWS SES SDK send email with attachments

问题

我正在使用官方的 AWS Golang SDK与 SES 进行集成,但找不到关于如何将一些附件(代码中表示为 []byte 的 PDF 文件)添加到电子邮件中的任何信息。

你能帮助我吗?

当前的电子邮件发送代码如下所示:

sesEmailInput := &ses.SendEmailInput{
	Destination: &ses.Destination{
		ToAddresses: []*string{aws.String("收件人地址")},
	},
	Message: &ses.Message{
		Subject: &ses.Content{
			Data: aws.String("一些文本"),
		},
		Body: &ses.Body{
			Html: &ses.Content{
				Data: aws.String("一些文本"),
			},
		},
	},
	Source: aws.String("发件人地址"),
	ReplyToAddresses: []*string{
		aws.String("发件人地址"),
	},
}
if _, err := s.sesSession.SendEmail(sesEmailInput); err != nil {
	return err
}
英文:

I'm using the official AWS Golang SDK to integrate with SES but can't find any information about how to add some attachments (pdf file represented as []byte in code) to the email.

Could you help me?

The current email sending code looks like this:

sesEmailInput := &ses.SendEmailInput{
	Destination: &ses.Destination{
		ToAddresses: []*string{aws.String("To address")},
	},
	Message: &ses.Message{
		Subject: &ses.Content{
			Data: aws.String("Some text"),
		},
		Body: &ses.Body{
			Html: &ses.Content{
				Data: aws.String("Some Text"),
			},
		},
	},
	Source: aws.String("From address"),
	ReplyToAddresses: []*string{
		aws.String("From address"),
	},
}
if _, err := s.sesSession.SendEmail(sesEmailInput); err != nil {
	return err
}

答案1

得分: 16

要发送附件,请使用SendRawEmail API而不是SendEmail。AWS文档通常将其称为构建“原始消息”,而不是明确说明如何发送附件。

以下是一个示例,来自AWS SDK for Go API参考文档:

params := &ses.SendRawEmailInput{
    RawMessage: &ses.RawMessage{ // Required
        Data: []byte("PAYLOAD"), // Required
    },
    ConfigurationSetName: aws.String("ConfigurationSetName"),
    Destinations: []*string{
        aws.String("Address"), // Required
        // More values...
    },
    FromArn:       aws.String("AmazonResourceName"),
    ReturnPathArn: aws.String("AmazonResourceName"),
    Source:        aws.String("Address"),
    SourceArn:     aws.String("AmazonResourceName"),
    Tags: []*ses.MessageTag{
        { // Required
            Name:  aws.String("MessageTagName"),  // Required
            Value: aws.String("MessageTagValue"), // Required
        },
        // More values...
    },
}
resp, err := svc.SendRawEmail(params)

进一步阅读:

英文:

To send attachments, use the SendRawEmail API instead of SendEmail. AWS documentation will generally refer to this as constructing a 'raw message' instead of explicitly calling out how to send attachments.

Example

From the AWS SDK for Go API Reference, linked below:

params := &ses.SendRawEmailInput{
    RawMessage: &ses.RawMessage{ // Required
        Data: []byte("PAYLOAD"), // Required
    },
    ConfigurationSetName: aws.String("ConfigurationSetName"),
    Destinations: []*string{
        aws.String("Address"), // Required
        // More values...
    },
    FromArn:       aws.String("AmazonResourceName"),
    ReturnPathArn: aws.String("AmazonResourceName"),
    Source:        aws.String("Address"),
    SourceArn:     aws.String("AmazonResourceName"),
    Tags: []*ses.MessageTag{
        { // Required
            Name:  aws.String("MessageTagName"),  // Required
            Value: aws.String("MessageTagValue"), // Required
        },
        // More values...
    },
}
resp, err := svc.SendRawEmail(params)

Further Reading

答案2

得分: 2

几个关于原始邮件的重要事项:

遵循以下结构:

boundary=boundary_name \n\n  (使用 boundary= 和 \n\n 创建一个边界)
--boundary_name              (使用 -- 开始一个边界)
  Header                     (使用 Content-Type: 添加头部)
                             (使用 \n 添加一个空行)
  html 或 text 或 file       (添加你的内容)
                             (使用 \n 添加一个空行)
--boundary_name-- \n\n       (使用 -- -- 和 \n\n 关闭边界)

PHP 代码示例:

$boundary = md5(time());

$html = "<h1>E-mail Test</h1>";
$html .= "<img src=\"cid:{$attachment['filename']}\">"; // Content-ID

$text = "You need HTML enabled";


$raw = '';
$raw .= "From:{$from}\n";
$raw .= "To:{$to}\n";
$raw .= "Subject:{$subject}\n";
$raw .= "MIME-Version: 1.0\n";
$raw .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\n\n";
$raw .= "--{$boundary}\n";

    $raw .= "Content-Type: multipart/alternative; boundary=\"sub_{$boundary}\"\n\n";
    $raw .= "--sub_{$boundary}\n";
        $raw .= "Content-Type: text/plain; charset=\"UTF-8\"\n";
        $raw .= "\n";
        $raw .= "{$text}\n";
        $raw .= "\n";
    $raw .= "--sub_{$boundary}\n";
        $raw .= "Content-Type: text/html; charset=\"UTF-8\"\n";
        $raw .= "Content-Disposition: inline\n";
        $raw .= "\n";
        $raw .= "{$html}\n";
        $raw .= "\n";
    $raw .= "--sub_{$boundary}--\n\n";

foreach ($this->email->getFiles() as $attachment) {
    $raw .= "--{$boundary}\n";
        $raw .= "Content-Type:{$attachment['mimetype']}; name=\"{$attachment['filename']}\"\n"; // name
        $raw .= "Content-Transfer-Encoding:base64\n";
        $raw .= "Content-Disposition:attachment;filename=\"{$attachment['filename']}\"\n"; // filename
        #$raw .= "Content-Disposition:inline;name={$file_name}\n";
        $raw .= "Content-ID:<{$attachment['filename']}>\n";
        $raw .= "\n";
        $raw .= base64_encode($attachment['content']) . "\n";
        $raw .= "\n";
}
$raw .= "--{$boundary}--\n\n";

最终的原始消息示例:

From:Name From<name@from.com>
To:email@to.com,second@to.com
Subject:Your subject
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="b4f53df7c26ae6945f29c42d5c2bb55f"

--b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type: multipart/alternative; boundary="sub_b4f53df7c26ae6945f29c42d5c2bb55f"

--sub_b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type: text/plain; charset="UTF-8"

You need HTML enabled

--sub_b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type: text/html; charset="UTF-8"
Content-Disposition: inline

<h1>E-mail Test</h1>
<img src="cid:qrcode.png"> // <-- from Header Content-ID:<name>

--sub_b4f53df7c26ae6945f29c42d5c2bb55f--

--b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type:image/png; name="qrcode.png"
Content-Transfer-Encoding:base64
Content-Disposition:attachment;filename="qrcode.png"
Content-ID:<qrcode.png> // you can use <img src="cid:qrcode.png"> in html

iVBORw0K== // base64 编码的文件内容

--b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type:image/png; name="another_file.png"
Content-Transfer-Encoding:base64
Content-Disposition:attachment;filename="another_file.png"
Content-ID:<another_file.png>

iVBORw0KGg== // base64 编码的文件内容

--b4f53df7c26ae6945f29c42d5c2bb55f--

不要忘记,在头部之后和内容之前都要有一个空行。

对于 PHP AWS SDK:

try {
    $client = new SesClient($options);
    $result = $client->sendRawEmail([
        'RawMessage' => [
            'Data' => $raw
        ],
    ]);
    echo $result['MessageId'];
}
catch (AwsException $e) {
    echo $e->getAwsErrorMessage();       
    return false;
}
英文:

after several wasted hours, things you should know about raw emails.

follow a structure like this:

boundary=boundary_name \n\n  (create a boundary with boundary= and \n\n)
--boundary_name              (start a boundary with --)
  Header                     (add headers with Content-Type:)
                             (one blank line with \n)
  html or text or file       (add your content)
                             (one blank line with \n)
--boundary_name-- \n\n       (close boundary with -- -- and \n\n)

Example with PHP code:

$boundary = md5(time());

$html = "<h1>E-mail Test</h1>";
$html .= "<img src=\"cid:{$attachment['filename']}\">"; // Content-ID

$text = "You need HTML enabled";


$raw = '';
$raw .= "From:{$from}\n";
$raw .= "To:{$to}\n";
$raw .= "Subject:{$subject}\n";
$raw .= "MIME-Version: 1.0\n";
$raw .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"\n\n";
$raw .= "--{$boundary}\n";

    $raw .= "Content-Type: multipart/alternative; boundary=\"sub_{$boundary}\"\n\n";
    $raw .= "--sub_{$boundary}\n";
        $raw .= "Content-Type: text/plain; charset=\"UTF-8\"\n";
        $raw .= "\n";
        $raw .= "{$text}\n";
        $raw .= "\n";
    $raw .= "--sub_{$boundary}\n";
        $raw .= "Content-Type: text/html; charset=\"UTF-8\"\n";
        $raw .= "Content-Disposition: inline\n";
        $raw .= "\n";
        $raw .= "{$html}\n";
        $raw .= "\n";
    $raw .= "--sub_{$boundary}--\n\n";

foreach ($this->email->getFiles() as $attachment) {
    $raw .= "--{$boundary}\n";
        $raw .= "Content-Type:{$attachment['mimetype']}; name=\"{$attachment['filename']}\"\n"; // name
        $raw .= "Content-Transfer-Encoding:base64\n";
        $raw .= "Content-Disposition:attachment;filename=\"{$attachment['filename']}\"\n"; // filename
        #$raw .= "Content-Disposition:inline;name={$file_name}\n";
        $raw .= "Content-ID:<{$attachment['filename']}>\n";
        $raw .= "\n";
        $raw .= base64_encode($attachment['content']) . "\n";
        $raw .= "\n";
}
$raw .= "--{$boundary}--\n\n";

Final raw Message example:

From:Name From<name@from.com>
To:email@to.com,second@to.com
Subject:Your subject
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="b4f53df7c26ae6945f29c42d5c2bb55f"

--b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type: multipart/alternative; boundary="sub_b4f53df7c26ae6945f29c42d5c2bb55f"

--sub_b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type: text/plain; charset="UTF-8"

You need HTML enabled

--sub_b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type: text/html; charset="UTF-8"
Content-Disposition: inline

<h1>E-mail Test</h1>
<img src="cid:qrcode.png"> // <-- from Header Content-ID:<name>

--sub_b4f53df7c26ae6945f29c42d5c2bb55f--

--b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type:image/png; name="qrcode.png"
Content-Transfer-Encoding:base64
Content-Disposition:attachment;filename="qrcode.png"
Content-ID:<qrcode.png> // you can use <img src="cid:qrcode.png"> in html

iVBORw0K== // base64encoded file contents

--b4f53df7c26ae6945f29c42d5c2bb55f
Content-Type:image/png; name="another_file.png"
Content-Transfer-Encoding:base64
Content-Disposition:attachment;filename="another_file.png"
Content-ID:<another_file.png>

iVBORw0KGg== // base64encoded file contents

--b4f53df7c26ae6945f29c42d5c2bb55f--

Don't forget, after Headers, one blank lines before and after content

For PHP AWS SDK

try {
    $client = new SesClient($options);
    $result = $client->sendRawEmail([
        'RawMessage' => [
            'Data' => $raw
        ],
    ]);
    echo $result['MessageId'];
}
catch (AwsException $e) {
    echo $e->getAwsErrorMessage();       
    return false;
}

答案3

得分: 1

SES原始消息必须进行base64编码。因此,您需要将文件内容作为缓冲区获取,并将其编码为base64字符串附件。此外,您不需要为原始消息数据创建新的缓冲区,因为它已经接受字符串数据类型。

可选:您还可以省略Destinations参数,因为您已经在原始消息数据中提供了To字段。(您也可以提供CcBcc字段)

您可以尝试以下示例代码:

const sendAttachmentEmail = async () => {
  // 您可以使用以下方式
  const DATA = await workbook.writeToBuffer(); // 这是生成的Excel工作簿
  // 或者使用以下方式
  const DATA = fs.readFileSync("files/demo-invoice.xlsx"); // 这是files文件夹中的Excel文件

  const SOURCE_EMAIL = "xyz@gmail.com";
  const TO_EMAIL = "abc@gmail.com";

  let ses_mail = "From: 'AWS SES Attchament Configuration' <" + SOURCE_EMAIL + ">\n";
  ses_mail += "To: " + TO_EMAIL + "\n";
  ses_mail += "Subject: AWS SES Attachment Example\n";
  ses_mail += "MIME-Version: 1.0\n";
  ses_mail += "Content-Type: multipart/mixed; boundary=\"NextPart\"\n\n";
  ses_mail += "--NextPart\n";
  ses_mail += "Content-Type: text/html\n\n";
  ses_mail += "This is the body of the email.\n\n";
  ses_mail += "--NextPart\n";
  ses_mail += "Content-Type: application/octet-stream; name=\"demo-invoice.xlsx\"\n";
  ses_mail += "Content-Transfer-Encoding: base64\n";
  ses_mail += "Content-Disposition: attachment\n\n";
  ses_mail += DATA.toString("base64").replace(/([^
const sendAttachmentEmail = async () => {
  // 您可以使用以下方式
  const DATA = await workbook.writeToBuffer(); // 这是生成的Excel工作簿
  // 或者使用以下方式
  const DATA = fs.readFileSync("files/demo-invoice.xlsx"); // 这是files文件夹中的Excel文件

  const SOURCE_EMAIL = "xyz@gmail.com";
  const TO_EMAIL = "abc@gmail.com";

  let ses_mail = "From: 'AWS SES Attchament Configuration' <" + SOURCE_EMAIL + ">\n";
  ses_mail += "To: " + TO_EMAIL + "\n";
  ses_mail += "Subject: AWS SES Attachment Example\n";
  ses_mail += "MIME-Version: 1.0\n";
  ses_mail += "Content-Type: multipart/mixed; boundary=\"NextPart\"\n\n";
  ses_mail += "--NextPart\n";
  ses_mail += "Content-Type: text/html\n\n";
  ses_mail += "This is the body of the email.\n\n";
  ses_mail += "--NextPart\n";
  ses_mail += "Content-Type: application/octet-stream; name=\"demo-invoice.xlsx\"\n";
  ses_mail += "Content-Transfer-Encoding: base64\n";
  ses_mail += "Content-Disposition: attachment\n\n";
  ses_mail += DATA.toString("base64").replace(/([^\0]{76})/g, "$1\n") + "\n\n";
  ses_mail += "--NextPart--";

  const params = {
    RawMessage: {
      Data: ses_mail
    },
    Source: "'AWS SES Attchament Configuration' <" + SOURCE_EMAIL + ">'"
  };

  return new Promise((resolve, reject) => {
    ses.sendRawEmail(params, (err) => {
      if (err) {
        return reject(err);
      }
      return resolve();
    });
  });
};
]{76})/g
, "$1\n") + "\n\n";
ses_mail += "--NextPart--"; const params = { RawMessage: { Data: ses_mail }, Source: "'AWS SES Attchament Configuration' <" + SOURCE_EMAIL + ">'" }; return new Promise((resolve, reject) => { ses.sendRawEmail(params, (err) => { if (err) { return reject(err); } return resolve(); }); }); };

注意:正则表达式替换/([^\0]{76})/g会将您的长行拆分,以确保邮件服务器不会因为有编码附件而抱怨消息行过长而导致暂时性退回。

英文:

SES raw messages must be base64-encoded. So, you'll need to get the file content as buffer and encode it as base64 string attachment. Also, you don't need to create a new buffer for raw message data since it already accepts a string data type.

OPTIONAL: You can also omit the Destinations parameter since you're already providing the To field in the raw message data. (You can also provide the Cc and Bcc fields as well)

You could try this for example:

const sendAttachmentEmail = async () =&gt; {
  // Yo can use by this way
  const DATA = await workbook.writeToBuffer(); // This workbook is excel generated
  // Or this way
  const DATA = fs.readFileSync(&quot;files/demo-invoice.xlsx&quot;); // This is excel file in files folder

  const SOURCE_EMAIL = &quot;xyz@gmail.com&quot;;
  const TO_EMAIL = &quot;abc@gmail.com&quot;;

  let ses_mail = &quot;From: &#39;AWS SES Attchament Configuration&#39; &lt;&quot; + SOURCE_EMAIL + &quot;&gt;\n&quot;;
  ses_mail += &quot;To: &quot; + TO_EMAIL + &quot;\n&quot;;
  ses_mail += &quot;Subject: AWS SES Attachment Example\n&quot;;
  ses_mail += &quot;MIME-Version: 1.0\n&quot;;
  ses_mail += &quot;Content-Type: multipart/mixed; boundary=\&quot;NextPart\&quot;\n\n&quot;;
  ses_mail += &quot;--NextPart\n&quot;;
  ses_mail += &quot;Content-Type: text/html\n\n&quot;;
  ses_mail += &quot;This is the body of the email.\n\n&quot;;
  ses_mail += &quot;--NextPart\n&quot;;
  ses_mail += &quot;Content-Type: application/octet-stream; name=\&quot;demo-invoice.xlsx\&quot;\n&quot;;
  ses_mail += &quot;Content-Transfer-Encoding: base64\n&quot;;
  ses_mail += &quot;Content-Disposition: attachment\n\n&quot;;
  ses_mail += data.toString(&quot;base64&quot;).replace(/([^
const sendAttachmentEmail = async () =&gt; {
// Yo can use by this way
const DATA = await workbook.writeToBuffer(); // This workbook is excel generated
// Or this way
const DATA = fs.readFileSync(&quot;files/demo-invoice.xlsx&quot;); // This is excel file in files folder
const SOURCE_EMAIL = &quot;xyz@gmail.com&quot;;
const TO_EMAIL = &quot;abc@gmail.com&quot;;
let ses_mail = &quot;From: &#39;AWS SES Attchament Configuration&#39; &lt;&quot; + SOURCE_EMAIL + &quot;&gt;\n&quot;;
ses_mail += &quot;To: &quot; + TO_EMAIL + &quot;\n&quot;;
ses_mail += &quot;Subject: AWS SES Attachment Example\n&quot;;
ses_mail += &quot;MIME-Version: 1.0\n&quot;;
ses_mail += &quot;Content-Type: multipart/mixed; boundary=\&quot;NextPart\&quot;\n\n&quot;;
ses_mail += &quot;--NextPart\n&quot;;
ses_mail += &quot;Content-Type: text/html\n\n&quot;;
ses_mail += &quot;This is the body of the email.\n\n&quot;;
ses_mail += &quot;--NextPart\n&quot;;
ses_mail += &quot;Content-Type: application/octet-stream; name=\&quot;demo-invoice.xlsx\&quot;\n&quot;;
ses_mail += &quot;Content-Transfer-Encoding: base64\n&quot;;
ses_mail += &quot;Content-Disposition: attachment\n\n&quot;;
ses_mail += data.toString(&quot;base64&quot;).replace(/([^\0]{76})/g, &quot;$1\n&quot;) + &quot;\n\n&quot;;
ses_mail += &quot;--NextPart--&quot;;
const params = {
RawMessage: {
Data: ses_mail
},
Source: &quot;&#39;AWS SES Attchament Configuration&#39; &lt;&quot; + SOURCE_EMAIL + &quot;&gt;&#39;&quot;
};
return new Promise((resolve, reject) =&gt; {
ses.sendRawEmail(params, (err) =&gt; {
if (err) {
return reject(err);
}
return resolve();
});
});
};
]{76})/g, &quot;$1\n&quot;) + &quot;\n\n&quot;; ses_mail += &quot;--NextPart--&quot;; const params = { RawMessage: { Data: ses_mail }, Source: &quot;&#39;AWS SES Attchament Configuration&#39; &lt;&quot; + SOURCE_EMAIL + &quot;&gt;&#39;&quot; }; return new Promise((resolve, reject) =&gt; { ses.sendRawEmail(params, (err) =&gt; { if (err) { return reject(err); } return resolve(); }); }); };

NOTE: The /([^\0]{76})/ regular expression replacement breaks your long lines to make sure that mail servers do not complain about message lines being too long when there is an encoded attachment, which might result in a transient bounce.

huangapple
  • 本文由 发表于 2017年5月1日 02:18:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/43709761.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定