メールの添付ファイルを送信する方法は?


283

Pythonを使用して添付ファイルを電子メールで送信する方法を理解できません。で簡単なメッセージを送信できましたsmtplib。メールで添付ファイルを送信する方法を誰かに説明してもらえますか?他の投稿がオンラインにあることは知っていますが、Pythonの初心者として、それらを理解するのは難しいと思います。


5
これは、複数のファイルを添付できる簡単な実装です。埋め込む画像の場合は、それらを参照することもできます。 datamakessense.com/...
AdrianBR

この便利なdrupal.org/project/mimemail/issues/911612は、画像の添付ファイルを関連タイプの子パーツに添付する必要があることがわかりました。ルートMIMEパーツに画像を添付すると、画像は添付アイテムリストに表示され、outlook365などのクライアントでプレビューできます。
-Hinchy、

@AdrianBR画像がPDFファイルの場合。pngはズーム時にピクセルの問題があるため、pngは私には適していません。
ピノキオ

回答:


416

ここに別のものがあります:

import smtplib
from os.path import basename
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate


def send_mail(send_from, send_to, subject, text, files=None,
              server="127.0.0.1"):
    assert isinstance(send_to, list)

    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach(MIMEText(text))

    for f in files or []:
        with open(f, "rb") as fil:
            part = MIMEApplication(
                fil.read(),
                Name=basename(f)
            )
        # After the file is closed
        part['Content-Disposition'] = 'attachment; filename="%s"' % basename(f)
        msg.attach(part)


    smtp = smtplib.SMTP(server)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.close()

最初の例とほとんど同じですが、立ち寄るほうが簡単です。


7
変更可能なデフォルト値を持つように注意してください: stackoverflow.com/questions/101268/hidden-features-of-python/...
グリンゴサーブ

11
@ user589983他のユーザーのように編集を提案してみませんか?残りの参照をfileに変更しましたf
オリ

9
Python3開発者への注意:モジュール「email.Utils」は「email.utils」に名前が変更されました
gecco

7
python2.5用+それを使用する方が簡単ですはMIMEApplicationを代わりに-と彼ループトンの最初の3行を減らす:part = MIMEApplication(open(f, 'rb').read())
マタ

5
送信されたメールに件名は表示されませんでした。行をmsg ['Subject'] = subjectに変更した後にのみ機能しました。私はpython 2.7を使用しています。
ルーク、

70

これはOlipython 3の修正バージョンです

import smtplib
from pathlib import Path
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email.utils import COMMASPACE, formatdate
from email import encoders


def send_mail(send_from, send_to, subject, message, files=[],
              server="localhost", port=587, username='', password='',
              use_tls=True):
    """Compose and send email with provided info and attachments.

    Args:
        send_from (str): from name
        send_to (list[str]): to name(s)
        subject (str): message title
        message (str): message body
        files (list[str]): list of file paths to be attached to email
        server (str): mail server host name
        port (int): port number
        username (str): server auth username
        password (str): server auth password
        use_tls (bool): use TLS mode
    """
    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = COMMASPACE.join(send_to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach(MIMEText(message))

    for path in files:
        part = MIMEBase('application', "octet-stream")
        with open(path, 'rb') as file:
            part.set_payload(file.read())
        encoders.encode_base64(part)
        part.add_header('Content-Disposition',
                        'attachment; filename="{}"'.format(Path(path).name))
        msg.attach(part)

    smtp = smtplib.SMTP(server, port)
    if use_tls:
        smtp.starttls()
    smtp.login(username, password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.quit()

感謝しますが、基本も
含め

あなたはあなたのファイルを閉じていないようです、それはガベージコレクションされるか、終了時に閉じられますが、それは悪い習慣です。open()をfとして使用するのが正しい方法です。
2017年

コードが機能しない。format(os.path.basename(f))の誤った変数名fはformat(os.path.basename(path))である必要があります
Chris

1
send_toはlist [str]である必要があります
Subin

2
私にとって最良の答えは、小さなエラーがあるけど:置き換えるimport pathlibfrom pathlib import Path
AleAve81

65

これは私が最終的に使用したコードです:

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email import Encoders


SUBJECT = "Email Data"

msg = MIMEMultipart()
msg['Subject'] = SUBJECT 
msg['From'] = self.EMAIL_FROM
msg['To'] = ', '.join(self.EMAIL_TO)

part = MIMEBase('application', "octet-stream")
part.set_payload(open("text.txt", "rb").read())
Encoders.encode_base64(part)

part.add_header('Content-Disposition', 'attachment; filename="text.txt"')

msg.attach(part)

server = smtplib.SMTP(self.EMAIL_SERVER)
server.sendmail(self.EMAIL_FROM, self.EMAIL_TO, msg.as_string())

コードはOliの投稿とほとんど同じです。皆さんありがとう

バイナリファイルの電子メールの添付ファイルの問題の投稿に基づくコード。


2
いい答えだ。サンプルの本文テキストを追加するコードも含まれていると便利です。
Steven Bluen 2015年

4
電子メールライブラリの最新リリースでは、モジュールのインポートが異なります。例:from email.mime.base import MIMEBase
Varun Balupuri

27
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
import smtplib

msg = MIMEMultipart()
msg.attach(MIMEText(file("text.txt").read()))
msg.attach(MIMEImage(file("image.png").read()))

# to send
mailer = smtplib.SMTP()
mailer.connect()
mailer.sendmail(from_, to, msg.as_string())
mailer.close()

ここから改作。


私が探しているものではありません。ファイルはメールの本文として送信されました。6行目と7行目には括弧が不足しています。ただし、近づいているように感じます
Richard

2
電子メールはプレーンテキストであり、それがsmtplibサポートしています。添付ファイルを送信するには、添付ファイルをMIMEメッセージとしてエンコードし、プレーンテキストのメールで送信します。ただし、新しいPythonメールモジュールがあります:docs.python.org/library/email.mime.html
Katriel

@katrienlalex実用的な例は私の理解を助けるのに大いに役立ちます
Richard

1
上記の例が機能しないことを確信していますか?便利なSMTPサーバーはありませんが、調べたところmsg.as_string()、確かにMIMEマルチパートメールの本文のように見えます。ウィキペディアはMIMEを説明しています:en.wikipedia.org/wiki/MIME
Katriel

1
Line 6, in <module> msg.attach(MIMEText(file("text.txt").read())) NameError: name 'file' is not defined
Benjamin2002

7

Python 3の別の方法(誰かが検索している場合):

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders

fromaddr = "sender mail address"
toaddr = "receiver mail address"

msg = MIMEMultipart()

msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "SUBJECT OF THE EMAIL"

body = "TEXT YOU WANT TO SEND"

msg.attach(MIMEText(body, 'plain'))

filename = "fileName"
attachment = open("path of file", "rb")

part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)

msg.attach(part)

server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "sender mail password")
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()

Gmailアカウントで「安全性の低いアプリ」を必ず許可してください


6

Gmailのバージョン。Python3.6で動作します(SMTP経由でメールを送信できるようにするには、Gmailの設定を変更する必要があります:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
from os.path import basename


def send_mail(send_from: str, subject: str, text: str, 
send_to: list, files= None):

    send_to= default_address if not send_to else send_to

    msg = MIMEMultipart()
    msg['From'] = send_from
    msg['To'] = ', '.join(send_to)  
    msg['Subject'] = subject

    msg.attach(MIMEText(text))

    for f in files or []:
        with open(f, "rb") as fil: 
            ext = f.split('.')[-1:]
            attachedfile = MIMEApplication(fil.read(), _subtype = ext)
            attachedfile.add_header(
                'content-disposition', 'attachment', filename=basename(f) )
        msg.attach(attachedfile)


    smtp = smtplib.SMTP(host="smtp.gmail.com", port= 587) 
    smtp.starttls()
    smtp.login(username,password)
    smtp.sendmail(send_from, send_to, msg.as_string())
    smtp.close()

使用法:

username = 'my-address@gmail.com'
password = 'top-secret'
default_address = ['my-address2@gmail.com'] 

send_mail(send_from= username,
subject="test",
text="text",
send_to= None,
files= # pass a list with the full filepaths here...
)

他のメールプロバイダーで使用するには、smtp設定を変更するだけです。


4

私が得ることができる最も簡単なコードは:

#for attachment email
from django.core.mail import EmailMessage

    def attachment_email(request):
            email = EmailMessage(
            'Hello', #subject
            'Body goes here', #body
            'MyEmail@MyEmail.com', #from
            ['SendTo@SendTo.com'], #to
            ['bcc@example.com'], #bcc
            reply_to=['other@example.com'],
            headers={'Message-ID': 'foo'},
            )

            email.attach_file('/my/path/file')
            email.send()

それは公式のDjangoドキュメントに基づいていました


3
あなたの場合、メールを送信するにはdjangoをインストールする必要があります...それは質問に適切に返答しません
comte

@comte 'coz pythonはDjangoでのみ使用されますよね?
Auspex 2017年

5
@Auspexそれが私のポイントです;-)それはLibreOfficeをインストールして設定ファイルを編集するようなものです
comte

これは役立つ情報です。1つのモジュールだけがインポートされ、その使用は、他のモジュールが通過するMIMEフープに比べて非常にシンプルでエレガントです。対照的に、あなたの例では、LibreOfficeはメモ帳よりも使いにくいです。
ビョークがナンバーワンのファン、

4

他の回答は素晴らしいですが、誰かが代替案を探している場合に備えて、別のアプローチを共有したかったのです。

ここでの主な違いは、このアプローチを使用すると、HTML / CSSを使用してメッセージをフォーマットできるため、クリエイティブになり、メールにスタイルを付けることができるという点です。HTMLを使用する必要はありませんが、プレーンテキストのみを使用することもできます。

この関数は、複数の受信者への電子メールの送信を受け入れ、複数のファイルを添付することもできます。

私はこれをPython 2で試しただけですが、3でも問題なく動作するはずです。

import os.path
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication

def send_email(subject, message, from_email, to_email=[], attachment=[]):
    """
    :param subject: email subject
    :param message: Body content of the email (string), can be HTML/CSS or plain text
    :param from_email: Email address from where the email is sent
    :param to_email: List of email recipients, example: ["a@a.com", "b@b.com"]
    :param attachment: List of attachments, exmaple: ["file1.txt", "file2.txt"]
    """
    msg = MIMEMultipart()
    msg['Subject'] = subject
    msg['From'] = from_email
    msg['To'] = ", ".join(to_email)
    msg.attach(MIMEText(message, 'html'))

    for f in attachment:
        with open(f, 'rb') as a_file:
            basename = os.path.basename(f)
            part = MIMEApplication(a_file.read(), Name=basename)

        part['Content-Disposition'] = 'attachment; filename="%s"' % basename
        msg.attach(part)

    email = smtplib.SMTP('your-smtp-host-name.com')
    email.sendmail(from_email, to_email, msg.as_string())

これが役に立てば幸いです!:-)


2
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
import mimetypes
import email.mime.application

smtp_ssl_host = 'smtp.gmail.com'  # smtp.mail.yahoo.com
smtp_ssl_port = 465
s = smtplib.SMTP_SSL(smtp_ssl_host, smtp_ssl_port)
s.login(email_user, email_pass)


msg = MIMEMultipart()
msg['Subject'] = 'I have a picture'
msg['From'] = email_user
msg['To'] = email_user

txt = MIMEText('I just bought a new camera.')
msg.attach(txt)

filename = 'introduction-to-algorithms-3rd-edition-sep-2010.pdf' #path to file
fo=open(filename,'rb')
attach = email.mime.application.MIMEApplication(fo.read(),_subtype="pdf")
fo.close()
attach.add_header('Content-Disposition','attachment',filename=filename)
msg.attach(attach)
s.send_message(msg)
s.quit()

説明については、適切に説明されているこのリンクを使用できます https://medium.com/@sdoshi579/to-send-an-email-along-with-attachment-using-smtp-7852e77623


2
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
import smtplib

msg = MIMEMultipart()

password = "password"
msg['From'] = "from_address"
msg['To'] = "to_address"
msg['Subject'] = "Attached Photo"
msg.attach(MIMEImage(file("abc.jpg").read()))
file = "file path"
fp = open(file, 'rb')
img = MIMEImage(fp.read())
fp.close()
msg.attach(img)
server = smtplib.SMTP('smtp.gmail.com: 587')
server.starttls()
server.login(msg['From'], password)
server.sendmail(msg['From'], msg['To'], msg.as_string())
server.quit()

2
こんにちは、ようこそ。理解を深めるために質問に答えるときは、必ず回答の説明を投稿してください
Ali

0

以下は、SoccerPlayerの投稿Hereから見つけたものと、xlsxファイルを簡単に添付できるようにする次のリンクの組み合わせです。ここで見つかりました

file = 'File.xlsx'
username=''
password=''
send_from = ''
send_to = 'recipient1 , recipient2'
Cc = 'recipient'
msg = MIMEMultipart()
msg['From'] = send_from
msg['To'] = send_to
msg['Cc'] = Cc
msg['Date'] = formatdate(localtime = True)
msg['Subject'] = ''
server = smtplib.SMTP('smtp.gmail.com')
port = '587'
fp = open(file, 'rb')
part = MIMEBase('application','vnd.ms-excel')
part.set_payload(fp.read())
fp.close()
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment', filename='Name File Here')
msg.attach(part)
smtp = smtplib.SMTP('smtp.gmail.com')
smtp.ehlo()
smtp.starttls()
smtp.login(username,password)
smtp.sendmail(send_from, send_to.split(',') + msg['Cc'].split(','), msg.as_string())
smtp.quit()

0

私のコードを使用すると、Gmailを使用してメールの添付ファイルを送信できます。

「で、Gmailのアドレス設定ここにSMTPメールを

Gmailアカウントのパスワードを " YOUR SMTP PASSWORD HERE_ "に設定してください

メッセージ_の受け取るために___EMAIL一部を、あなたは、宛先のメールアドレスを設定する必要があります。

アラーム通知が件名です。

誰かが部屋に入ってきました、添付の写真は体です

["/home/pi/webcam.jpg"]は画像の添付ファイルです。

#!/usr/bin/env python
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
import os

USERNAME = "___YOUR SMTP EMAIL HERE___"
PASSWORD = "__YOUR SMTP PASSWORD HERE___"

def sendMail(to, subject, text, files=[]):
    assert type(to)==list
    assert type(files)==list

    msg = MIMEMultipart()
    msg['From'] = USERNAME
    msg['To'] = COMMASPACE.join(to)
    msg['Date'] = formatdate(localtime=True)
    msg['Subject'] = subject

    msg.attach( MIMEText(text) )

    for file in files:
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(file,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"'
                       % os.path.basename(file))
        msg.attach(part)

    server = smtplib.SMTP('smtp.gmail.com:587')
    server.ehlo_or_helo_if_needed()
    server.starttls()
    server.ehlo_or_helo_if_needed()
    server.login(USERNAME,PASSWORD)
    server.sendmail(USERNAME, to, msg.as_string())
    server.quit()

sendMail( ["___EMAIL TO RECEIVE THE MESSAGE__"],
        "Alarm notification",
        "Someone has entered the room, picture attached",
        ["/home/pi/webcam.jpg"] )

久しぶり!あなたがあなたのコードを適切に帰属し、それを答えに直接含めているのを見るのは良いことです。ただし、複数の質問に同じ回答コードをコピーして貼り付けることは、一般的に好ましくありません。それら同じソリューションで本当に解決できる場合は、代わりに質問に重複としてフラグを立てる必要があります。
Das_Geek

0

電子メールに添付するファイルの種類を指定することもできます。例として、pdfを使用しました。

def send_email_pdf_figs(path_to_pdf, subject, message, destination, password_path=None):
    ## credits: http://linuxcursor.com/python-programming/06-how-to-send-pdf-ppt-attachment-with-html-body-in-python-script
    from socket import gethostname
    #import email
    from email.mime.application import MIMEApplication
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    import smtplib
    import json

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    with open(password_path) as f:
        config = json.load(f)
        server.login('me@gmail.com', config['password'])
        # Craft message (obj)
        msg = MIMEMultipart()

        message = f'{message}\nSend from Hostname: {gethostname()}'
        msg['Subject'] = subject
        msg['From'] = 'me@gmail.com'
        msg['To'] = destination
        # Insert the text to the msg going by e-mail
        msg.attach(MIMEText(message, "plain"))
        # Attach the pdf to the msg going by e-mail
        with open(path_to_pdf, "rb") as f:
            #attach = email.mime.application.MIMEApplication(f.read(),_subtype="pdf")
            attach = MIMEApplication(f.read(),_subtype="pdf")
        attach.add_header('Content-Disposition','attachment',filename=str(path_to_pdf))
        msg.attach(attach)
        # send msg
        server.send_message(msg)

inspirations / credits to:http : //linuxcursor.com/python-programming/06-how-to-send-pdf-ppt-attachment-with-html-body-in-python-script

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.