【问题标题】:Add embedded image in emails in AWS SES service在 AWS SES 服务的电子邮件中添加嵌入图像
【发布时间】:2018-02-02 16:56:19
【问题描述】:

我正在尝试编写一个可以发送电子邮件以指定电子邮件的 Java 应用程序。在电子邮件中,我还想附上一些图片。

请在下面找到我的代码:-

public class AmazonSESSample {

    static final String FROM = "abc@gmail.com";
    static final String TO = "def@gmail.com";
    static final String BODY = "This email was sent through Amazon SES by using the AWS SDK for Java. hello";
    static final String SUBJECT = "Amazon SES test (AWS SDK for Java)";

    public static void main(String[] args) throws IOException {
        Destination destination = new Destination().withToAddresses(new String[] { TO });
        Content subject = new Content().withData(SUBJECT);
        Message msg = new Message().withSubject(subject);
        // Include a body in both text and HTML formats
        //Content textContent = new Content().withData("Hello - I hope you're having a good day.");
        Content htmlContent = new Content().withData("<h2>Hi User,</h2>\n"
                + " <h3>Please find the ABC Association login details below</h3>\n"
                + " <img src=\"logo.png\" alt=\"Mountain View\">\n"
                + " Click <a href=\"http://google.com">here</a> to go to the association portal.\n"
                + " <h4>Association ID - 12345</h4>\n" + "  <h4>Admin UID - suny342</h4>\n"
                + " <h4>Password - poass234</h4>\n" + " Regards,\n" + " <br>Qme Admin</br>");
        Body body = new Body().withHtml(htmlContent);
        msg.setBody(body);
        SendEmailRequest request = new SendEmailRequest().withSource(FROM).withDestination(destination)
                .withMessage(msg);
        try {
            System.out.println("Attempting to send an email through Amazon SES by using the AWS SDK for Java...");
            AWSCredentials credentials = null;
            credentials = new BasicAWSCredentials("ABC", "CDF");
            try {
                // credentialsProvider.
            } catch (Exception e) {
                throw new AmazonClientException("Cannot load the credentials from the credential profiles file. "
                        + "Please make sure that your credentials file is at the correct "
                        + "location (/Users/iftekharahmedkhan/.aws/credentials), and is in valid format.", e);
            }
            AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard()
                    .withCredentials(new AWSStaticCredentialsProvider(credentials)).withRegion("us-west-2").build();
            client.sendEmail(request);
            System.out.println("Email sent!");
        } catch (Exception ex) {
            System.out.println("The email was not sent.");
            System.out.println("Error message: " + ex.getMessage());
        }
    }
}

图像已放置在资源目录中,但未嵌入到电子邮件中。谁能帮忙。

【问题讨论】:

  • 请不要多次发布同一个问题。

标签: java amazon-web-services email aws-lambda amazon-ses


【解决方案1】:

您需要使用图像本身的绝对公共 路径或data URL,而不是相对路径。例如:

<img src=\"https://example.com/logo.png\" alt=\"Mountain View\" />

<img src=\"data:image/png;base64, {BASE64_ENCODED_DATA}\" alt=\"Mountain View\" />

编辑

截至 2020 年 1 月,Gmail 仍不支持 base64 编码图像。

【讨论】:

  • 要添加到 Khalid 的好答案,请考虑使用存储在 S3 中的图像的 URL 等。您的电子邮件较小,您可以在访问图像时通过跟踪获取有关正在打开的电子邮件的信息。如果您对这些细节感兴趣,请不要在图片前面使用 CDN。
  • 我对此表示怀疑。也许base64编码的数据有问题。您是否在常规 HTML 页面上对其进行过测试?
  • 这对我也不起作用。只发送简单的一个像素图像,gmail 没有显示它,并且显示为图像未找到图标。 data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQYV2P4DwABAQEAWk1v8QAAAABJRU5ErkJggg== - 这是图片
  • 很遗憾,当收件人使用 gmail 时,这将不起作用。
  • @ZephaniahGrunschlag:感谢您指出这一点。目前,是的,Gmail 不支持 base64 编码的图像,但谁知道呢?他们可能会像 2012 年和 2018 年一样再次改变主意 :) 我会更新答案。
【解决方案2】:

我能够使用 AWS SES 发送一封电子邮件,其中包含可以在 GMail 客户端中看到的图像,方法是将图像附加到邮件中并使用对它们的内联处置引用。

我使用in the AWS docs 解释的代码将图像附加到 MimeMessage,然后使用 HTML 中的cid 引用到这些图像(如in this post answer 解释)。

首先,我们将图像附加到消息中,添加几个特定属性(标题和处置):

        MimeMultipart msg = new MimeMultipart("mixed");        
        DataSource fds = new FileDataSource("/path/to/my/image.png");
        att.setDataHandler(new DataHandler(fds));
        att.setFileName(fds.getName());         
        att.setHeader("Content-ID","<myImage>");
        att.setDisposition("inline; filename=\"image.png\"");
        msg.addBodyPart(att);

请注意,Content-ID 属性中的&lt;&gt;必须存在,其中包含您选择的任何ID(在我的示例中为myImage)。

那么,在消息体的 HTML 中,我们只需要添加每张图片的 cid(内容 id)即可:

<img src="cid:myImage">

对于完整的代码,我几乎使用了上面的 AWS 参考(使用相同的变量名),所做的唯一更改是 setHeadersetDisposition 方法。

【讨论】:

    【解决方案3】:

    @sebagra 发布的方法效果很好。

    在 Python 使用 boto3ses 客户端的情况下,将 Content-Disposition 设置为内联的方法是:

        att.add_header('Content-ID', '<myImage>')
        att.add_header('Content-Disposition', 'inline', filename=os.path.basename(IMAGE_PATH))
    

    基于python示例in the AWS docs的完整示例:

        import os
        import boto3
        from botocore.exceptions import ClientError
        from email.mime.multipart import MIMEMultipart
        from email.mime.text import MIMEText
        from email.mime.application import MIMEApplication
        
        # Replace sender@example.com with your "From" address.
        # This address must be verified with Amazon SES.
        SENDER = "Sender Name <sender@example.com>"
        
        # Replace recipient@example.com with a "To" address. If your account 
        # is still in the sandbox, this address must be verified.
        RECIPIENT = "recipient@example.com"
        
        # Specify a configuration set. If you do not want to use a configuration
        # set, comment the following variable, and the 
        # ConfigurationSetName=CONFIGURATION_SET argument below.
        CONFIGURATION_SET = "ConfigSet"
        
        # If necessary, replace us-west-2 with the AWS Region you're using for Amazon SES.
        AWS_REGION = "us-west-2"
        
        # The subject line for the email.
        SUBJECT = "Customer service contact info"
        
        # The full path to the file that will be attached to the email.
        IMAGE_PATH = "path/to/myImage.png"
        
        # The email body for recipients with non-HTML email clients.
        BODY_TEXT = "Hello,\r\nPlease see the attached file for a list of customers to contact."
        
        # The HTML body of the email.
        BODY_HTML = """\
        <html>
        <head></head>
        <body>
        <h1>Hello!</h1>
        <p>Please see the attached file for a list of customers to contact.</p>
        </body>
        </html>
        """
        
        # The character encoding for the email.
        CHARSET = "utf-8"
        
        # Create a new SES resource and specify a region.
        client = boto3.client('ses',region_name=AWS_REGION)
        
        # Create a multipart/mixed parent container.
        msg = MIMEMultipart('mixed')
        # Add subject, from and to lines.
        msg['Subject'] = SUBJECT 
        msg['From'] = SENDER 
        msg['To'] = RECIPIENT
        
        # Create a multipart/alternative child container.
        msg_body = MIMEMultipart('alternative')
        
        # Encode the text and HTML content and set the character encoding. This step is
        # necessary if you're sending a message with characters outside the ASCII range.
        textpart = MIMEText(BODY_TEXT.encode(CHARSET), 'plain', CHARSET)
        htmlpart = MIMEText(BODY_HTML.encode(CHARSET), 'html', CHARSET)
        
        # Add the text and HTML parts to the child container.
        msg_body.attach(textpart)
        msg_body.attach(htmlpart)
        
        # Define the attachment part and encode it using MIMEApplication.
        att = MIMEApplication(open(IMAGE_PATH, 'rb').read())
        
        # Add a header to tell the email client to treat this part as an attachment,
        # and set an id and content disposition.
        att.add_header('Content-ID', '<myImage>')
        att.add_header('Content-Disposition', 'inline', filename=os.path.basename(IMAGE_PATH))
        
        # Attach the multipart/alternative child container to the multipart/mixed
        # parent container.
        msg.attach(msg_body)
        
        # Add the attachment to the parent container.
        msg.attach(att)
    
        try:
            response = client.send_raw_email(
                Source=SENDER,
                Destinations=[
                    RECIPIENT
                ],
                RawMessage={
                    'Data': msg.as_string(),
                }
            )
        # Display an error if something goes wrong. 
        except ClientError as e:
            print(e.response['Error']['Message'])
        else:
            print("Email sent! Message ID:"),
            print(response['MessageId'])
    

    如果使用sesv2msg 的构建方式相同,但要使用的 api 是 send_email

        ...
        client = boto3.client('sesv2',region_name=AWS_REGION)
        ...
        response = client.send_email(
            FromEmailAddress=SENDER,
            Destination={
                'ToAddresses': [
                    RECIPIENT
                ]
            },
            Content={
                'Raw': {
                    'Data': msg.as_string()
                }
            }
        )
        ...
    

    【讨论】:

      【解决方案4】:

      我使用 AWS SES 将内联 base 64 图像发送到 Yahoo 帐户没有问题。当我尝试发送到 GMail 帐户时,我遇到了麻烦。我发送的文本已渲染,但图像未显示。

      我发现 GMail 没有剥离图像。它只是没有显示它。我通过在 GMail 中查看邮件时选择更多 -> “显示原件”来确认这一点。

      【讨论】:

        猜你喜欢
        • 2019-03-01
        • 2020-10-04
        • 2018-09-27
        • 1970-01-01
        • 2022-11-09
        • 2020-09-16
        • 2014-10-30
        • 1970-01-01
        • 2010-10-29
        相关资源
        最近更新 更多