368 Stimmen

Wie sende ich E-Mail-Anhänge?

Ich habe Probleme, zu verstehen, wie man eine Anlage mit Python per E-Mail versendet. Ich habe erfolgreich einfache Nachrichten mit dem smtplib verschickt. Könnte mir bitte jemand erklären, wie man eine Anlage in einer E-Mail versendet. Ich weiß, dass es andere Beiträge online gibt, aber als Python-Anfänger fällt es mir schwer, sie zu verstehen.

6 Stimmen

Hier ist eine einfache Implementierung, die mehrere Dateien anhängen kann und sogar in Bezug auf Bilder eingebettet werden kann. datamakessense.com/…

0 Stimmen

Ich fand das nützlich drupal.org/project/mimemail/issues/911612 stellt sich heraus, dass Bilddateianhänge an einen damit verbundenen Typ-Kindteil angehängt werden müssen. Wenn Sie das Bild an den Wurzel-MIME-Teil anhängen, können die Bilder in der Liste der angehängten Elemente angezeigt und in Clienten wie Outlook365 vorab angezeigt werden.

0voto

Charlie Parker Punkte 13101

Sie können auch den Typ des Anhangs angeben, den Sie in Ihrer E-Mail möchten. Als Beispiel habe ich pdf verwendet:

def send_email_pdf_figs(path_to_pdf, subject, message, destination, password_path=None):
    ## inspirations/credits to: 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('ich@gmail.com', config['password'])
        # Nachricht erstellen (obj)
        msg = MIMEMultipart()

        message = f'{message}\nVersendet von Hostname: {gethostname()}'
        msg['Betreff'] = subject
        msg['Von'] = 'ich@gmail.com'
        msg['An'] = destination
        # Text in die E-Mail-Nachricht einfügen
        msg.attach(MIMEText(message, "plain"))
        # PDF an die E-Mail-Nachricht anhängen
        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)
        # Nachricht senden
        server.send_message(msg)

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

0voto

Versuchen Sie dies, ich hoffe, es könnte helfen

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 = "deine E-Mail hier"
toaddr = input("Geben Sie die E-Mail-Adresse ein, an die Sie senden möchten: ")

# Instanz von MIMEMultipart
msg = MIMEMultipart()

# die E-Mail-Adresse des Absenders speichern
msg['From'] = fromaddr

# die E-Mail-Adresse des Empfängers speichern
msg['To'] = toaddr

# den Betreff speichern
msg['Subject'] = input("Was ist der Betreff:\t")
# String, um den Inhalt der E-Mail zu speichern
body = input("Was ist der Inhalt:\t")

# den Inhalt an die Nachricht anhängen
msg.attach(MIMEText(body, 'plain'))

# die Datei öffnen, die gesendet werden soll
filename = input("Dateiname:")
attachment = open(filename, "rb")

# Instanz von MIMEBase und als p benannt
p = MIMEBase('application', 'octet-stream')

# Um den Payload in codierter Form zu ändern
p.set_payload((attachment).read())

# in Base64 codieren
encoders.encode_base64(p)

p.add_header('Content-Disposition', "Anhang; Dateiname= %s" % filename)

# die Instanz 'p' an die Instanz 'msg' anhängen
msg.attach(p)

# Sitzung erstellen SMTP erstellen
s = smtplib.SMTP('smtp.gmail.com', 587)

# TLS für Sicherheit starten
s.starttls()

# Authentifizierung
s.login(fromaddr, "deinpassworthier")

# Konvertiert die Multipart-Nachricht in einen String
text = msg.as_striren()

# die E-Mail senden
s.sendmail(fromaddr, toaddr, text)

# die Sitzung beenden
s.quit()

0voto

Titus Cheserem Punkte 69

Ich hatte ein wenig Mühe, mein Skript dazu zu bringen, generische Anhänge zu versenden, aber nach ein wenig Recherche und dem Durchblättern der Artikel in diesem Beitrag bin ich schließlich auf folgendes gekommen

# to query:
import sys
import ast
from datetime import datetime

import smtplib
import mimetypes
from email.mime.application import MIMEApplication
from email.mime.multipart import MIMEMultipart
from email import encoders
from email.message import Message
from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.text import MIMEText

from dotenv import load_dotenv, dotenv_values

load_dotenv()  # load environment variables from .env

'''
sample .env file
# .env file
SECRET_KEY="gnhfpsjxxxxxxxx"
DOMAIN="GMAIL"
TOP_LEVEL_DOMAIN="COM"
EMAIL="CHESERExxxxxx@${DOMAIN}.${TOP_LEVEL_DOMAIN}"
TO_ADDRESS = ("cheseremxxxxx@gmail.com","cheserek@gmail.com")#didn't use this in the code but you can load recipients from here
'''

import smtplib

tls_port = 587
ssl_port = 465
smtp_server_domain_names = {'GMAIL': ('smtp.gmail.com', tls_port, ssl_port),
                            'OUTLOOK': ('smtp-mail.outlook.com', tls_port, ssl_port),
                            'YAHOO': ('smtp.mail.yahoo.com', tls_port, ssl_port),
                            'AT&T': ('smtp.mail.att.net', tls_port, ssl_port),
                            }

# todo: Ability to choose mail server provider
# auto read in from the dictionary the respective mail server address and the tls and ssl ports

class Bimail:
    def __init__(self, subject, recipients):
        self.subject = subject
        self.recipients = recipients
        self.htmlbody = ''
        self.mail_username = 'will be loaded from .env file'
        self.mail_password = 'loaded from .env file as well'
        self.attachments = []

    # Creating an smtp object
    # todo: if gmail passed in use gmail's dictionary values

    def setup_mail_client(self, domain_key_to_use="GMAIL",
                          email_servers_domains_dict=smtp_server_domain_names):
        """

        :param report_pdf:
        :type to_address: str
        """
        smtpObj = None
        encryption_status = True
        config = dotenv_values(".env")
        # check if the domain_key exists from within the available email-servers-domains dict file passed in
        # else throw an error

        # read environment file to get the Domain to be used
        if f"{domain_key_to_use}" in email_servers_domains_dict.keys():
            # if the key is found do the following
            # 1.extract the domain,tls,ssl ports from email_servers dict for use in program
            try:
                values_tuple = email_servers_domains_dict.get(f"{domain_key_to_use}")
                ssl_port = values_tuple[2]
                tls_port = values_tuple[1]
                smtp_server = values_tuple[0]

                smtpObj = smtplib.SMTP(smtp_server, tls_port)
                print(f"Success connect with tls on {tls_port}")
                print('Awaiting for connection encryption via startttls()')
                encryption_status = False

            except:
                print(f"Failed connection via tls on port {tls_port}")
                try:
                    smtpObj = smtplib.SMTP_SSL(smtp_server, ssl_port)
                    print(f"Success connect with ssl on {ssl_port}")
                    encryption_status = True
                except:
                    print(f"Failed connection via ssl on port {ssl_port}")
            finally:
                print("Within Finally block")
                if not smtpObj:
                    print("Failed!!!  no Internet connection")
                else:
                    # if connection channel is unencrypted via the use of tls encrypt it
                    if not encryption_status:
                        status = smtpObj.starttls()
                        if status[0] == 220:
                            print("Successfully Encrypted tls channel")

                    print("Successfully Connected!!!! Requesting Login")
                    # Loading .env file values to config variable
                    #load Login Creds from ENV File
                    self.mail_username = f'{config.get("EMAIL")}'
                    self.mail_password = f'{cofig.get("SECRET_KEY")}'

                    status = smtpObj.login(self.mail_usernam,self.mail_password) 

                    if status[0] == 235:
                        print("Successfully Authenticated User to xxx account")
                        success = self.send(smtpObj, f'{config.get("EMAIL")}')
                        if not bool(success):
                            print(f"Success in Sending Mail to  {success}")
                            print("Disconnecting from Server INstance")
                            quit_result = smtpObj.quit()

                        else:
                            print(f"Failed to Post {success}!!!")
                            print(f"Quiting anyway !!!")
                            quit_result = smtpObj.quit()
                    else:
                        print("Application Specific Password is Required")
        else:

            print("World")

    def send(self,smtpObj,from_address):
        msg = MIMEMultipart('alternative')
        msg['From'] = from_address
        msg['Subject'] = self.subject
        msg['To'] = ", ".join(self.recipients)  # to must be array of the form ['mailsender135@gmail.com']
        msg.preamble = "preamble goes here"
        # check if there are attachments if yes, add them
        if self.attachments:
            self.attach(msg)
        # add html body after attachments
        msg.attach(MIMEText(self.htmlbody, 'html'))
        # send
        print(f"Attempting Email send to the following addresses {self.recipients}")
        result = smtpObj.sendmail(from_address, self.recipients,msg.as_string())
        return result

    def htmladd(self, html):
        self.htmlbody = self.htmlbody + '<p></p>' + html

    def attach(self, msg):
        for f in self.attachments:

            ctype, encoding = mimetypes.guess_type(f)
            if ctype is None or encoding is not None:
                ctype = "application/octet-stream"

            maintype, subtype = ctype.split("/", 1)

            if maintype == "text":
                fp = open(f)
                # Note: we should handle calculating the charset
                attachment = MIMEText(fp.read(), _subtype=subtype)
                fp.close()
            elif maintype == "image":
                fp = open(f, "rb")
                attachment = MIMEImage(fp.read(), _subtype=subtype)
                fp.close()

            elif maintype == "ppt":
                fp = open(f, "rb")
                attachment = MIMEApplication(fp.read(), _subtype=subtype)
                fp.close()

            elif maintype == "audio":
                fp = open(f, "rb")
                attachment = MIMEAudio(fp.read(), _subtype=subtype)
                fp.close()
            else:
                fp = open(f, "rb")
                attachment = MIMEBase(maintype, subtype)
                attachment.set_payload(fp.read())
                fp.close()
                encoders.encode_base64(attachment)
            attachment.add_header("Content-Disposition", "attachment", filename=f)
            attachment.add_header('Content-ID', '<{}>'.format(f))
            msg.attach(attachment)

    def addattach(self, files):
        self.attachments = self.attachments + files

# example below
if __name__ == '__main__':
    # subject and recipients
    mymail = Bimail('Sales email ' + datetime.now().strftime('%Y/%m/%d'),
                    ['cheseremxx@gmail.com', 'tkemboxxx@gmail.com'])
    # start html body. Here we add a greeting.
    mymail.htmladd('Good morning, find the daily summary below.')
    # Further things added to body are separated by a paragraph, so you do not need to worry about newlines for new sentences
    # here we add a line of text and an html table previously stored in the variable
    mymail.htmladd('Daily sales')
    mymail.addattach(['htmlsalestable.xlsx'])
    # another table name + table
    mymail.htmladd('Daily bestsellers')
    mymail.addattach(['htmlbestsellertable.xlsx'])
    # add image chart title
    mymail.htmladd('Weekly sales chart')
    # attach image chart
    mymail.addattach(['saleschartweekly.png'])
    # refer to image chart in html
    mymail.htmladd('<img src="cid:saleschartweekly.png"/>')
    # attach another file
    mymail.addattach(['MailSend.py'])
    # send!

    mymail.setup_mail_client( domain_key_to_use="GMAIL",email_servers_domains_dict=smtp_server_domain_names)

0 Stimmen

Dieser Code scheint für Python 3.5 oder früher geschrieben worden zu sein. Die email-Bibliothek wurde in Version 3.6 überarbeitet und ist jetzt deutlich vielseitiger und logischer. Wahrscheinlich sollten Sie das, was Sie haben, wegwerfen und mit den Beispielen aus der email-Dokumentation neu beginnen.

0 Stimmen

Ich würde smtpObj.sendmail() vermeiden und stattdessen smtpObj.send_message(msg) verwenden. Erstens ist es einfacher und zweitens habe ich Probleme mit der sendmail-Funktion festgestellt, die ich nicht erklären kann.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X