boto SES send_email
クライアントを使用して画像の添付ファイルを送信するにはどうすればよいですか?
send_raw_email
を使用して添付ファイルを送信できることはわかっていますが、html data
を使用してメッセージ本文を送信する必要があります。これが不可能な場合、boto3.ses.send_raw_email()を使用してHTMLデータを含むメールを送信するにはどうすればよいですか?
" Amazon SESを使用してHTMLメールを送信する方法 "の恥知らずなコピーの例これは、典型的なメールデータコンテンツの例です。
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テキストを送信する場合は、上記のメッセージ辞書を使用して渡すだけです。 (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
内に添付ファイルを配置する必要があります。
他のSO質問、ブログ、Pythonのドキュメントなど)を含むいくつかのソースを調べた後、以下のコードを思いつきました。
テキストおよび/またはhtmlメールおよび添付ファイルを可能にします。
Boto3の代わりにSMTPクライアントで電子メールを送信するなど、他の目的でMIMEを再利用する場合に備えて、MIMEと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 <[email protected]>'.
: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 <[email protected]>'
recipients_ = ['Recipient One <[email protected]>', '[email protected]']
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_)
これは私が添付ファイルを送信するのに役立ちました:
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='[email protected]', 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='[email protected]',file_name="yourFile.txt")
@adklの答えを拡張するために、Amazonの独自の例では、古い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()
メソッドをサポートするファイルのようなオブジェクトを使用できます。
2019年3月
[〜#〜] updated [〜#〜]公式ドキュメント( 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 [email protected] with your "From" address.
# This address must be verified with Amazon SES.
SENDER = "Sender Name <[email protected]>"
# Replace [email protected] with a "To" address. If your account
# is still in the sandbox, this address must be verified.
RECIPIENT = "[email protected]"
# 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'])
これは、pythonバージョン2.7.xを使用して実装することもできます。
以下はこれのための作業コードです-
[注-追加する「送信者」と「受信者」は、AWS SESで確認する必要があります。 OR 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 <[email protected]>",
"recipients_" : ['Recipient One <[email protected]>','Recipient two <[email protected]>'],
"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_)
これが私が最終的に使用したクラスです。 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=[]):
""" 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
"""
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()
}
)