Attach CSV to E-Mail with MIMEBase, only attaches 'bin' document

微笑、不失礼 提交于 2021-01-29 10:47:58

问题


I want to write a function to attach a csv file to an E-Mail with HTML text. Everything works fine. I sends the E-Mail with the text and the attachment with the right information. Only the data format is wrong. I tried different varieties in MIMEBASE('application', 'octet-stream'). This one gives me a '.bin' data which I cannot open on macOS. Others gave me a plain text data which included the right data, but I don't wanna copy it manually into a csv. Does someone have a solution how I get out the data as '.csv'? Most of the solutions I found here just looked like my code below.

Code:

def send_mail(receiver, subject, filepath, attachname):
    
    #login information
    port = 123
    smtp_server = "test.server.com"
    login = "testlogin" # your login 
    password = "12345678910" # your password 

    # specify the sender’s and receiver’s email addresses and text in HTML
    sender = "testmail@test.com"
    receiver = receiver
    message = MIMEMultipart()
    message["Subject"] = subject
    message["From"] = sender
    message["To"] = COMMASPACE.join([receiver])
    html_text = """\
    <html>
      <body>
        <p>Hi ,<br>
        <p>kind regards</p>
        <p> This is an automatized Mail </p>
      </body>
    </html>
    """
    # convert both parts to MIMEText objects and add them to the MIMEMultipart message
    text = MIMEText(html_text, "html")
    message.attach(text)
    
    #add a file as attachment
    file = open(filepath, "rb")
    att = MIMEBase('application', 'octet-stream')
    att.set_payload(file.read())
    encoders.encode_base64(att)
    att.add_header("Content_Disposition",
                    'attachment', filename = attachname)
    message.attach(att)
    try:
        #send your message with credentials specified above
        with smtplib.SMTP(smtp_server, port) as server:
            server.connect(smtp_server, port)
            server.ehlo()
            server.starttls()
            server.ehlo()
            server.login(login, password)
            server.sendmail(sender, receiver, message.as_string())

        # tell the script to report if your message was sent or which errors need to be fixed 
        print('Sent')
    except (gaierror, ConnectionRefusedError):
        print('Failed to connect to the server. Bad connection settings?')
    except smtplib.SMTPServerDisconnected:
        print('Failed to connect to the server. Wrong user/password?')
    except smtplib.SMTPException as e:
        print('SMTP error occurred: ' + str(e))

send_mail('testmail@test.com', 'TEST', '/Users/Changer/Desktop/test.csv', 'test.csv')

回答1:


Email clients may use the content type of the attachment part to determine which program is used to open the attachment, so specifying a suitable content type may help.

This code uses the standard library's mimetypes module to try to guess the correct content type of the attachment, based on its name:

import mimetypes

mimetypes.init()

def send_mail(receiver, subject, filepath, attachname):
    ...

    mimetype, _ = mimetypes.guess_type(attachname)
    if mimetype is None:
        mimetype = 'application/octet-stream'
    type_, _, subtype = mimetype.partition('/')
    att = MIMEBase(type_, subtype)
    ...

The above code will generate these headers for the attachment:

b'Content-Type: text/x-comma-separated-values'
b'MIME-Version: 1.0'
b'Content-Transfer-Encoding: base64'
b'Content_Disposition: attachment; filename="test.csv"'

Whether a mac will open a csv with a spreadsheet application (I assume this is what you want) depends on the configuration of the machine (See this blog for an example). If you want to be sure open the file in a spreadsheet it might be more effective to convert it to a spreadsheet format and send the spreadsheet.



来源:https://stackoverflow.com/questions/64010242/attach-csv-to-e-mail-with-mimebase-only-attaches-bin-document

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!