如何使用boto3 SES Quantidade
客户端发送图片附件?
我知道我可以使用send_email
发送附件,但我需要使用send_raw_email
发送邮件正文。如果无法做到这一点,我如何使用boto3.ses.send_raw_email()发送包含html数据的电子邮件?
答案 0 :(得分:9)
浏览了包括其他SO问题,博客和Python文档在内的多个资源之后,我想到了下面的代码。
允许使用文本和/或html电子邮件和附件。
将MIME和boto3部分分开,以防万一您想将MIME再次用于其他目的,例如使用SMTP客户端而不是boto3发送电子邮件。
import os
import boto3
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
def create_multipart_message(
sender: str, recipients: list, title: str, text: str=None, html: str=None, attachments: list=None)\
-> MIMEMultipart:
"""
Creates a MIME multipart message object.
Uses only the Python `email` standard library.
Emails, both sender and recipients, can be just the email string or have the format 'The Name <the_email@host.com>'.
:param sender: The sender.
:param recipients: List of recipients. Needs to be a list, even if only one recipient.
:param title: The title of the email.
:param text: The text version of the email body (optional).
:param html: The html version of the email body (optional).
:param attachments: List of files to attach in the email.
:return: A `MIMEMultipart` to be used to send the email.
"""
multipart_content_subtype = 'alternative' if text and html else 'mixed'
msg = MIMEMultipart(multipart_content_subtype)
msg['Subject'] = title
msg['From'] = sender
msg['To'] = ', '.join(recipients)
# Record the MIME types of both parts - text/plain and text/html.
# According to RFC 2046, the last part of a multipart message, in this case the HTML message, is best and preferred.
if text:
part = MIMEText(text, 'plain')
msg.attach(part)
if html:
part = MIMEText(html, 'html')
msg.attach(part)
# Add attachments
for attachment in attachments or []:
with open(attachment, 'rb') as f:
part = MIMEApplication(f.read())
part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachment))
msg.attach(part)
return msg
def send_mail(
sender: str, recipients: list, title: str, text: str=None, html: str=None, attachments: list=None) -> dict:
"""
Send email to recipients. Sends one mail to all recipients.
The sender needs to be a verified email in SES.
"""
msg = create_multipart_message(sender, recipients, title, text, html, attachments)
ses_client = boto3.client('ses') # Use your settings here
return ses_client.send_raw_email(
Source=sender,
Destinations=recipients,
RawMessage={'Data': msg.as_string()}
)
if __name__ == '__main__':
sender_ = 'The Sender <the_sender@email.com>'
recipients_ = ['Recipient One <recipient_1@email.com>', 'recipient_2@email.com']
title_ = 'Email title here'
text_ = 'The text version\nwith multiple lines.'
body_ = """<html><head></head><body><h1>A header 1</h1><br>Some text."""
attachments_ = ['/path/to/file1/filename1.txt', '/path/to/file2/filename2.txt']
response_ = send_mail(sender_, recipients_, title_, text_, body_, attachments_)
print(response_)
答案 1 :(得分:4)
来自&#34; HOW TO SEND HTML MAILS USING AMAZON SES &#34;的无耻复制示例 这就是典型的电子邮件数据内容的样子。
message_dict = { 'Data':
'From: ' + mail_sender + '\n'
'To: ' + mail_receivers_list + '\n'
'Subject: ' + mail_subject + '\n'
'MIME-Version: 1.0\n'
'Content-Type: text/html;\n\n' +
mail_content}
如果您想使用boto3.ses.send_raw_email发送附件和HTML文本,则只需使用上面的消息dict并传递即可。 (只需将你的html文本放在mail_content下)
response = client.send_raw_email(
Destinations=[
],
FromArn='',
RawMessage=message_dict,
ReturnPathArn='',
Source='',
SourceArn='',
)
实际上,原始附件标头应该在send_email()和send_raw_email()中都有效。除send_mail外,您应将附件放在Text
内,而不是html
。
答案 2 :(得分:3)
这对我发送附件很有用:
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import boto.ses
AWS_ACCESS_KEY = 'HEREYOURACCESSKEY'
AWS_SECRET_KEY = 'HEREYOURSECRETKEY'
class Email(object):
def __init__(self, to, subject):
self.to = to
self.subject = subject
self.text = None
self.attachment = None
def text(self, text):
self.text = text
def add_attachment(self, attachment):
self.attachment = attachment
def send(self, from_addr=None, file_name = None):
connection = boto.ses.connect_to_region(
'us-east-1',
aws_access_key_id=AWS_ACCESS_KEY,
aws_secret_access_key=AWS_SECRET_KEY
)
msg = MIMEMultipart()
msg['Subject'] = self.subject
msg['From'] = from_addr
msg['To'] = self.to
part = MIMEApplication(self.attachment)
part.add_header('Content-Disposition', 'attachment', filename=file_name)
part.add_header('Content-Type', 'application/vnd.ms-excel; charset=UTF-8')
msg.attach(part)
# the message body
part = MIMEText(self.text)
msg.attach(part)
return connection.send_raw_email(msg.as_string(),source=from_addr,destinations=self.to)
if __name__ == "__main__":
email = Email(to='toMail@gmail.com', subject='Your subject!')
email.text('This is a text body.')
#you could use StringIO.StringIO() to get the file value
email.add_attachment(yourFileValue)
email.send(from_addr='from@mail.com',file_name="yourFile.txt")
答案 3 :(得分:2)
要扩展@adkl的答案,亚马逊自己的示例是使用旧的Python处理电子邮件和附件的方式。没关系,只是这些模块上的当前文档不全面,可能会使像我这样的新用户感到困惑。
这是有关通过CSV附件形成邮件的简单示例。
from email.message import EmailMessage
def create_email_message(sender: str, recipients: list, title: str, text: str,
attachment: BytesIO, file_name: str) -> EmailMessage:
msg = EmailMessage()
msg["Subject"] = title
msg['From'] = sender
msg['To'] = ', '.join(recipients)
msg.set_content(text)
data = attachment.read()
msg.add_attachment(
data,
maintype="text",
subtype="csv",
filename=file_name
)
return msg
# Client init, attachment file creation here
message = create_email_message(...)
try:
ses.send_raw_email(
Source=sender,
Destinations=recipients,
RawMessage={'Data': message.as_string()}
)
except ClientError as e:
logger.exception(f"Cannot send email report to {recipients}: {e}")
else:
logger.info("Sent report successfully")
在此示例中,我使用BytesIO
对象作为附件的来源,但是您可以使用任何支持read()
方法的类似文件的对象。
答案 4 :(得分:2)
这是我最后使用的课程。放入Lambda文件并使用它。
接受附件的文件名列表。发送HTML
电子邮件。为\n
更改<br />
我将下面的类[1]保存为emailer.py
并用作:
from emailer import Emailer
def lambda_handler(event, context):
# ...
emailer = Emailer()
emailer.send(
to=email_recipients_list,
subject=subject_string,
fromx=from_address_string,
body=email_body_string,
attachments=attachments_list
)
[1]
import boto3
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
class Emailer(object):
""" send email with attachments """
def send(self, to, subject, fromx, body=None, content=None, attachments=None):
""" sends email with attachments
Parameters:
* to (list or comma separated string of addresses): recipient(s) address
* fromx (string): from address of email
* body (string, optional): Body of email ('\n' are converted to '< br/>')
* content (string, optional): Body of email specified as filename
* attachments (list, optional): list of paths of files to attach
"""
if attachments is None:
attachments = []
self.to = to
self.subject = subject
self.fromx = fromx
self.attachment = None
self.body = body
self.content = content
self.attachments = attachments
if type(self.to) is list:
self.to = ",".join(self.to)
message = MIMEMultipart()
message['Subject'] = self.subject
message['From'] = self.fromx
message['To'] = self.to
if self.content and os.path.isfile(self.content):
part = MIMEText(open(str(self.content)).read().replace("\n", "<br />"), "html")
message.attach(part)
elif self.body:
part = MIMEText(self.body.replace("\\n", "<br />").replace("\n", "<br />"), "html")
message.attach(part)
for attachment in self.attachments:
part = MIMEApplication(open(attachment, 'rb').read())
part.add_header('Content-Disposition', 'attachment', filename=attachment.split("/")[-1])
message.attach(part)
ses = boto3.client('ses', region_name='us-east-1')
response = ses.send_raw_email(
Source=message['From'],
Destinations=message['To'].split(","),
RawMessage={
'Data': message.as_string()
}
)
答案 5 :(得分:1)
2019年3月
以下是已更新官方文档(https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-raw.html)中粘贴复制的解决方案:
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.
ATTACHMENT = "path/to/customers-to-contact.xlsx"
# 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(ATTACHMENT, 'rb').read())
# Add a header to tell the email client to treat this part as an attachment,
# and to give the attachment a name.
att.add_header('Content-Disposition','attachment',filename=os.path.basename(ATTACHMENT))
# 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)
#print(msg)
try:
#Provide the contents of the email.
response = client.send_raw_email(
Source=SENDER,
Destinations=[
RECIPIENT
],
RawMessage={
'Data':msg.as_string(),
},
ConfigurationSetName=CONFIGURATION_SET
)
# 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'])
答案 6 :(得分:0)
这也可以使用python版本2.7.x来实现
以下是此的工作代码-
[注意-您添加的“发件人”和“收件人”必须在AWS SES中进行验证。或SES必须从“沙盒”状态移至“生产”状态
import os
import boto3
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
def create_multipart_message(email_metadata):
sender = email_metadata['sender_']
recipients = email_metadata['recipients_']
title = email_metadata['title_']
text = email_metadata['text_']
html = email_metadata['body_']
attachments = email_metadata['attachments_']
multipart_content_subtype = 'alternative' if text and html else 'mixed'
msg = MIMEMultipart(multipart_content_subtype)
msg['Subject'] = title
msg['From'] = sender
msg['To'] = ', '.join(recipients)
# Record the MIME types of both parts - text/plain and text/html.
# According to RFC 2046, the last part of a multipart message, in this case the HTML message, is best and preferred.
if text:
part = MIMEText(text, 'plain')
msg.attach(part)
if html:
part = MIMEText(html, 'html')
msg.attach(part)
# Add attachments
for attachment in attachments or []:
with open(attachment, 'rb') as f:
part = MIMEApplication(f.read())
part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(attachment))
msg.attach(part)
return msg
def send_mail(email_metadata):
#sender: str, recipients: list, title: str, text: str=None, html: str=None, attachments: list=None) -> dict:
"""
Send email to recipients. Sends one mail to all recipients.
The sender needs to be a verified email in SES.
"""
msg = create_multipart_message(email_metadata)
ses_client = boto3.client('ses') # Use your settings here
return ses_client.send_raw_email(
Source=email_metadata['sender_'],
Destinations=email_metadata['recipients_'],
RawMessage={'Data': msg.as_string()}
)
if __name__ == '__main__':
email_metadata = {
"sender_" : "The Sender <the_sender@email.com>",
"recipients_" : ['Recipient One <recipient_1@email.com>','Recipient two <recipient_2@email.com>'],
"title_" : "Email title here",
"text_" : "The text version\nwith multiple lines.",
"body_" : "<html><head></head><body><h1>A header 1</h1><br>Some text.",
"attachments_" : ['/path/to/file1/filename1.txt','/path/to/file2/filename2.txt']
}
response_ = send_mail(email_metadata)
print(response_)