Bagaimana cara mengirim lampiran email?

283

Saya mengalami masalah dalam memahami cara mengirim email lampiran menggunakan Python. Saya telah berhasil mengirim email pesan sederhana dengan smtplib. Bisakah seseorang tolong jelaskan bagaimana cara mengirim lampiran dalam email. Saya tahu ada posting lain secara online tetapi sebagai pemula Python saya menemukan mereka sulit dimengerti.

Richard
sumber
5
inilah implementasi sederhana yang dapat melampirkan banyak file, dan bahkan merujuknya dalam kasus gambar untuk disematkan. datamakessense.com/...
AdrianBR
Saya menemukan ini drupal.org/project/mimemail/issues/911612 berguna ternyata lampiran gambar harus dilampirkan ke bagian anak jenis terkait. Jika Anda melampirkan gambar ke bagian MIME root, gambar dapat muncul di daftar item terlampir, dan dipratinjau di klien seperti outlook365.
Hinchy
@ AdrianBR bagaimana jika saya memiliki gambar sebagai file PDF. Png memiliki masalah piksel saat memperbesar sehingga png tidak baik untuk saya.
Pinocchio

Jawaban:

416

Ini yang lain:

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()

Sama seperti contoh pertama ... Tapi itu seharusnya lebih mudah untuk diterima.

Oli
sumber
7
Hati-hati dengan standar yang bisa berubah: stackoverflow.com/questions/101268/hidden-features-of-python/…
Gringo Suave
11
@ user589983 Mengapa tidak menyarankan edit seperti yang dilakukan pengguna lain di sini? Saya telah mengubah referensi yang tersisa filemenjadi f.
Oli
9
Pemberitahuan untuk pengembang Python3: module "email.Utils" telah diubah namanya menjadi "email.utils"
gecco
7
untuk python2.5 + lebih mudah menggunakan MIMEApplication sebagai gantinya - mengurangi tiga baris pertama dari loop ke:part = MIMEApplication(open(f, 'rb').read())
mata
5
Subjek tidak ditampilkan dalam email yang dikirim. Hanya berfungsi setelah mengubah baris ke msg ['Subjek'] = subjek. Saya menggunakan python 2.7.
Luke
70

Ini adalah versi yang dimodifikasi dari Oliuntuk python 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()
Ehsan Iran-Nejad
sumber
terima kasih tetapi akan menyenangkan juga memiliki dasar: sintaks untuk satu file terlampir (menggunakan jalurnya)
JinSnow
Sepertinya Anda tidak menutup file Anda, itu akan menjadi sampah yang dikumpulkan atau ditutup saat keluar tetapi itu kebiasaan buruk. dengan open () sebagai f: adalah cara yang benar.
comte
Kode tidak berfungsi. Nama variabel f ​​yang salah dalam format (os.path.basename (f)) harus berupa format (os.path.basename (path))
Chris
1
send_to harus daftar [str]
Subin
2
jawaban terbaik untuk saya tetapi ada kesalahan kecil: ganti import pathlibdenganfrom pathlib import Path
AleAve81
65

ini kode yang akhirnya saya gunakan:

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())

Kode hampir sama dengan pos Oli. Terima kasih semuanya

Kode berdasarkan dari posting masalah lampiran file Binary email .

Richard
sumber
2
Jawaban yang bagus. Akan lebih baik jika juga berisi kode yang menambahkan contoh teks isi
Steven Bluen
4
Harap dicatat, dalam rilis modern perpustakaan email - impor modul berbeda. mis .: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()

Diadaptasi dari sini .

Oli
sumber
Tidak cukup apa yang saya cari. File dikirim sebagai badan surel. Ada juga tanda kurung yang hilang pada baris 6 dan 7. Saya merasa bahwa kita semakin dekat
Richard
2
Email adalah teks biasa, dan itulah yang smtplibmendukung. Untuk mengirim lampiran, Anda menyandikannya sebagai pesan MIME dan mengirimkannya dalam email plaintext. Ada modul email python baru, meskipun: docs.python.org/library/email.mime.html
Katriel
@katrienlalex contoh yang bekerja akan sangat membantu pemahaman saya
Richard
1
Apakah Anda yakin contoh di atas tidak berfungsi? Saya tidak memiliki server SMTP yang praktis, tetapi saya melihat msg.as_string()dan itu terlihat seperti badan email multipart MIME. Wikipedia menjelaskan 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

Cara lain dengan python 3 (Jika seseorang mencari):

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()

Pastikan untuk mengizinkan " aplikasi yang kurang aman " di akun Gmail Anda

Sudarshan
sumber
6

Versi Gmail, bekerja dengan Python 3.6 (perhatikan bahwa Anda perlu mengubah pengaturan Gmail Anda untuk dapat mengirim email melalui smtp dari itu:

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()

Pemakaian:

username = '[email protected]'
password = 'top-secret'
default_address = ['[email protected]'] 

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

Untuk digunakan dengan penyedia email lain, cukup ubah konfigurasi smtp.

Ferrarezi
sumber
4

Kode paling sederhana yang bisa saya dapatkan adalah:

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

    def attachment_email(request):
            email = EmailMessage(
            'Hello', #subject
            'Body goes here', #body
            '[email protected]', #from
            ['[email protected]'], #to
            ['[email protected]'], #bcc
            reply_to=['[email protected]'],
            headers={'Message-ID': 'foo'},
            )

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

Itu didasarkan pada dokumentasi resmi Django

Andrade
sumber
3
dalam kasus Anda, Anda harus menginstal Django untuk mengirim email ... itu tidak menjawab pertanyaan dengan benar
comte
@comte 'coz python hanya digunakan untuk Django, bukan?
Auspex
5
@Auspex itu maksud saya ;-) itu seperti menginstal LibreOffice untuk mengedit file konfigurasi ...
comte
Saya menemukan ini bermanfaat dan informatif. hanya satu modul yang diimpor, dan penggunaannya cukup sederhana dan elegan dibandingkan dengan simpai MIME yang dilompati orang lain. Dalam contoh Anda, sebaliknya, LibreOffice lebih sulit digunakan daripada notepad.
3pitt
4

Jawaban lain sangat bagus, walaupun saya masih ingin berbagi pendekatan yang berbeda jika seseorang mencari alternatif.

Perbedaan utama di sini adalah bahwa dengan menggunakan pendekatan ini Anda dapat menggunakan HTML / CSS untuk memformat pesan Anda, sehingga Anda bisa menjadi kreatif dan memberikan gaya pada email Anda. Meskipun Anda tidak dipaksa untuk menggunakan HTML, Anda juga masih dapat menggunakan teks biasa.

Perhatikan bahwa fungsi ini menerima pengiriman email ke banyak penerima dan juga memungkinkan untuk melampirkan banyak file.

Saya hanya mencoba ini di Python 2, tapi saya pikir itu harus berfungsi dengan baik pada 3 juga:

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: ["[email protected]", "[email protected]"]
    :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())

Saya harap ini membantu! :-)

Antony Fuentes Artavia
sumber
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()

Untuk penjelasan, Anda dapat menggunakan tautan ini menjelaskan dengan benar https://medium.com/@sdoshi579/to-send-an-email-along-with-attachment-using-smtp-7852e77623

sdoshi
sumber
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()
Abdul Haseeb
sumber
2
hai, Selamat datang, Harap selalu memposting penjelasan tentang jawaban Anda saat menjawab pertanyaan untuk pemahaman yang lebih baik
Ali
0

Di bawah ini adalah kombinasi dari apa yang saya temukan dari posting SoccerPlayer di sini dan tautan berikut yang membuatnya lebih mudah bagi saya untuk melampirkan file xlsx. Ditemukan di sini

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()
TonyRyan
sumber
0

Dengan kode saya, Anda dapat mengirim lampiran email menggunakan gmail, Anda harus:

setel alamat gmail Anda di " EMAIL SMTP ANDA DI SINI "

setel kata sandi akun gmail Anda di " PASSWORD SMTP ANDA DI SINI "

Di bagian ___EMAIL UNTUK MENERIMA PESAN_ Anda perlu mengatur alamat email tujuan.

Pemberitahuan alarm adalah subjek,

Seseorang telah memasuki ruangan, gambar terlampir adalah tubuh

["/home/pi/webcam.jpg"] adalah lampiran gambar.

#!/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"] )
John Rua
sumber
Lama tidak bertemu! Senang melihat bahwa Anda menghubungkan kode Anda dengan benar dan memasukkannya langsung ke dalam jawabannya. Namun, umumnya disukai untuk menyalin-tempel kode jawaban yang sama pada beberapa pertanyaan. Jika mereka benar - benar dapat diselesaikan dengan solusi yang sama, Anda harus menandai pertanyaan sebagai duplikat .
Das_Geek
0

Anda juga dapat menentukan jenis lampiran yang Anda inginkan dalam email Anda, sebagai contoh saya menggunakan 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('[email protected]', config['password'])
        # Craft message (obj)
        msg = MIMEMultipart()

        message = f'{message}\nSend from Hostname: {gethostname()}'
        msg['Subject'] = subject
        msg['From'] = '[email protected]'
        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)

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

Pinokio
sumber