Python email MIME attachment filename - python-2.7

I'm having trouble attaching a CSV file to an email. I can send the email fine using smtplib, and I can attach my CSV file to the email. But I cannot set the name of the attached file, and so I cannot set it to be .csv. Also I can't figure out how to add a text message to the body of the email.
This code results in an attachment called AfileName.dat, not the desired testname.csv, or better still attach.csv
#!/usr/bin/env python
import smtplib
from email.mime.multipart import MIMEMultipart
from email import Encoders
from email.MIMEBase import MIMEBase
def main():
print"Test run started"
sendattach("Test Email","attach.csv", "testname.csv")
print "Test run finished"
def sendattach(Subject,AttachFile, AFileName):
msg = MIMEMultipart()
msg['Subject'] = Subject
msg['From'] = "from#email.com"
msg['To'] = "to#email.com"
#msg['Text'] = "Here is the latest data"
part = MIMEBase('application', "octet-stream")
part.set_payload(open(AttachFile, "rb").read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename=AFileName')
msg.attach(part)
server = smtplib.SMTP("smtp.com",XXX)
server.login("from#email.com","password")
server.sendmail("email#email.com", "anotheremail#email.com", msg.as_string())
if __name__=="__main__":
main()

In the line part.add_header('Content-Disposition', 'attachment; filename=AFileName') you are hardcoding AFileName as part of the string and are not using the the same named function's argument.
To use the argument as the filename change it to
part.add_header('Content-Disposition', 'attachment', filename=AFileName)
To add a body to your email
from email.mime.text import MIMEText
msg.attach(MIMEText('here goes your body text', 'plain'))

Related

IICS taskflow - Notification task - attach file

I have an IICS taskflow with a mapping task and a notification task. The target of the mapping task is a csv stored in a server location.
With the notification task, I want to send an email with the csv attached. Do you know if this is possible or if is there another way to get to send the target csv by email??
Not the ideal solution, but you can write a simple python program to send the csv as an email, just provide the path of the csv to python program. and then, execute the python script from informatica as a command task. (IF Success) it is super easy to use a python script.
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os
import shutil
def send_mail(body_text, fromaddr, recipient_list, smtp_login, smtp_pass, file_path):
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = ', '.join(recipient_list)
msg['Subject'] = 'your Subject variable'
msg.attach(MIMEText(body_text, 'plain'))
filename = os.path.basename(file_path)
attachment = open(file_path, "rb")
part = MIMEBase('multipart', 'mixed; name=%s' % filename)
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= %s" % filename)
msg.attach(part)
server = smtplib.SMTP(host="your.mailserver.com", port=123)
# eg smtp.google.com
server.starttls()
server.login(smtp_login, smtp_pass)
text = msg.as_string()
server.set_debuglevel(1)
server.sendmail(fromaddr, recipient_list, text)
server.quit()
mainDir = '/path/to/file'
sendFileName = 'yourfilename' + '.csv'
sourceFilePath = mainDir + 'file_send/filename.csv'
body_text = '''
Dear All,
Please find attached document
Thank You.
'''
smtp_login = "emailusername"
smtp_pass = "emaipassword"
recipient_list = ['abc#company.com', 'def#company.com']
file_path = os.path.abspath(sendFilePath)
fromaddr = 'emailusername#company.com'
send_mail(body_text=body_text, fromaddr=fromaddr, recipient_list=recipient_list, smtp_login=smtp_login, smtp_pass=smtp_pass,
file_path=file_path)
This code may needs some modifications but thought it might help someone.

How to put line breaks in text of an email sent using mime and smtplib in python

I have built a code to read from excel and send email through python. I can't figure out how to put line breaks inside the text. For example, My code sends email as "Hello Team The handler for this week of date1 to date2 is Name1. The handler for next week of date2 to date3 is Name2.".
I want the email to read as:
"Hello Team
The handler for this week of date1 to date2 is Name1.
The The handler for next week of date3 to date4 is Name2."
Dates and names are extracted from an excel spreadsheet.
import email.message
import smtplib
from email.mime.multipart import MIMEMultipart
from openpyxl import load_workbook
gmail_user = "someone#gmail.com"
gmail_appPassword = "password"
sent_from = ['someone#gmail.com']
to = ['anyone#gmail.com']
import datetime,xlrd
book =
xlrd.open_workbook("C:/Users/shabib/Desktop/simple_excelmail.xlsx")
sh = book.sheet_by_index(0)
a1=sh.cell_value(rowx=0, colx=0)
b1=sh.cell_value(rowx=0, colx=1)
a1_as_date = datetime.datetime(*xlrd.xldate_as_tuple(a1, book.datemode))
b1_as_date = datetime.datetime(*xlrd.xldate_as_tuple(b1, book.datemode))
from datetime import date
x1=date.today()
for rx in range(sh.nrows):
text1= "Hello Team The handler for the week of: "'%s'%
a1_as_date.date(),"to " '%s' % b1_as_date.date(),"is "'%s'%
sh.cell_value(rowx=0, colx=2),"."
text1a=str(text1).strip('()').replace("'",'').replace(",",'')
print (text1a)
SUBJECT = "Weekly Rotation"
message = 'Subject: {}\n\n{}'.format(SUBJECT, msg)
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login(gmail_user, gmail_appPassword)
server.sendmail(sent_from, to, message)
server.quit()
If you send your text in html you will have a much greater ability to edit it. I included an example of some things you can do if you use this format. The html for break is <br>.
import smtplib
# Import the email modules we'll need
from email.mime.text import MIMEText
#html is the email body. We are gonna wrap some text around the analysis text
html=''
html = """\
<html>
<head></head>
<body>
<p>All,<br><br>Here is an email with some breaks"""
#this is just an example of how you can add to the text.
html+="""\
<br>Thanks,<br><br>
<font color="blue">Bort Simpson</font><br>
<font color="blue">Environmental Scientist</font><br>
<font color="blue">Technical Analysis Section</font><br>
</p>
</body>
</html>
"""
#this uses MIMEtext the create an email message
msg = MIMEText(html, 'html')
# me = 'bcubrich#gmail.com'
me = 'your_email_address#whatever.com'
you=['recipient_1#whatever.com','recipient_2#whatever.com']
#the email has some attributes we can edit, like the subject
msg['Subject'] = 'subject'
msg['From'] = me
msg['To'] = ", ".join(you) #create a string of recipients from a list
server = smtplib.SMTP('your.server', 25)
server.sendmail(me, you, msg.as_string()) #send message
Found the answer:
import email.message
import smtplib
from email.mime.multipart import MIMEMultipart
from openpyxl import load_workbook
gmail_user = "someone#gmail.com"
gmail_appPassword = "password"
sent_from = ['someone#gmail.com']
to = ['anyone#gmail.com']
import datetime,xlrd
book = xlrd.open_workbook("C:/Users/shabib/Desktop/Python_Scripts/Email_List.xlsx")
sh = book.sheet_by_index(0)
a1=sh.cell_value(rowx=0, colx=0)
b1=sh.cell_value(rowx=0, colx=1)
a1_as_date = datetime.datetime(*xlrd.xldate_as_tuple(a1,
book.datemode))
b1_as_date = datetime.datetime(*xlrd.xldate_as_tuple(b1,
book.datemode))
from datetime import date
x1=date.today()
for rx in range(sh.nrows):
text1="Hello Team,"+'\r'+"The handler for the week of: "+'\r'+"(This Week) "+str(a1_as_date.date())+" to "+str(b1_as_date.date())+" is "'%s'%sh.cell_value(rowx=0, colx=2)
SUBJECT = "Queue Managerment & Huddle Facilitator"
message = 'Subject: {}\n\n{}'.format(SUBJECT, text1)
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login(gmail_user, gmail_appPassword)
server.sendmail(sent_from, to, message)
server.quit()

Convert Google Doc to PDF and send email with PDF attachment

I am attempting to convert a Google Doc to a PDF (using the Drive API) and then attaching the file to an email (using the Gmail API).
The script runs, coverts the Google Doc to a PDF, sends an email with the attachment, but the PDF attachment is blank / corrupt.
I suspect the issue is with line: msg.set_payload(fh.read())
The relevant documentation: set_payload and io.Bytes()
Any guidance is greatly appreciated.
import base64
import io
from apiclient.http import MediaIoBaseDownload
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
fileId = '1234'
content_type = 'application/pdf'
response = drive.files().export_media(fileId=fileId, mimeType=content_type)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, response)
done = False
while done is False:
status, done = downloader.next_chunk()
logging.info("Download %d%%." % int(status.progress() * 100))
message = MIMEMultipart()
message['to'] = 'myemail#gmail.com'
message['from'] = 'myemail#gmail.com'
message['subject'] = 'test subject'
msg = MIMEText('test body')
message.attach(msg)
main_type, sub_type = content_type.split('/', 1)
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fh.read()) # i suspect the issue is here
msg.add_header('Content-Disposition', 'attachment', filename='an example file name.pdf')
message.attach(msg)
message_obj = {'raw': base64.urlsafe_b64encode(message.as_string())}
service.users().messages().send(userId="me", body=message_obj).execute()
How about this modification? I think that about the download from Google Drive, your script is correct. So I would like to propose to modify the script for sending an email with the attachment file.
I thought that msg.set_payload(fh.read()) is one of the modification points as you say. So the data retrieved by getvalue() was converted by email.encoders.encode_base64(). And also I modified message_obj.
Modified script:
Please modify as follows.
From:
msg = MIMEText('test body')
message.attach(msg)
main_type, sub_type = content_type.split('/', 1)
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fh.read()) # i suspect the issue is here
msg.add_header('Content-Disposition', 'attachment', filename='an example file name.pdf')
message.attach(msg)
message_obj = {'raw': base64.urlsafe_b64encode(message.as_string())}
service.users().messages().send(userId="me", body=message_obj).execute()
To:
from email import encoders # Please add this.
msg = MIMEText('test body')
message.attach(msg)
main_type, sub_type = content_type.split('/', 1)
msg = MIMEBase(main_type, sub_type)
msg.set_payload(fh.getvalue()) # Modified
encoders.encode_base64(msg) # Added
msg.add_header('Content-Disposition', 'attachment', filename='an example file name.pdf')
message.attach(msg)
message_obj = {'raw': base64.urlsafe_b64encode(message.as_bytes()).decode()} # Modified
service.users().messages().send(userId="me", body=message_obj).execute()
Note:
This modification supposes that you have already been able to send emails using Gmail API. If you cannot use Gmail API, please confirm the scopes and whether Gmail API is enabled at API console.
In my environment, I could confirm that the modified script worked. But if this didn't work in your environment, I apologize.

Is it possible to save the sent email into the sent items folder using python?

I want to sends an email but sent mail is empty.
how to send an email, and then put a copy of it in the "Sent" mail folder.
what can i do?
Yes, its possible.
Basicaly you need to create an MIME email and then send it throug smptlib and than save it on Sent with imaplib.
The official imaplib documentation.
More detailed examples of using imaplib.
Here is an example:
import time
import ssl
import imaplib
import smtplib
import email
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
class Mail:
def __init__(self):
# considering the same user and pass for smtp an imap
self.mail_user = 'youruser#yourdomain.com'
self.mail_pass = 'pass'
self.mail_host = 'mail.yourdomain'
def send_email(self, to, subject, body, path, attach):
message = MIMEMultipart()
message["From"] = self.mail_user
message["To"] = to
message["Subject"] = subject
message.attach(MIMEText(body, "plain"))
with open(path + attach, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
"attachment; filename= \"" + attach + "\"",
)
message.attach(part)
text = message.as_string()
context = ssl.create_default_context()
with smtplib.SMTP_SSL(self.mail_host, 465, context=context) as server:
result = server.login(self.mail_user, self.mail_pass)
server.sendmail(self.mail_user, to, text)
imap = imaplib.IMAP4_SSL(self.mail_host, 993)
imap.login(self.mail_user, self.mail_pass)
imap.append('INBOX.Sent', '\\Seen', imaplib.Time2Internaldate(time.time()), text.encode('utf8'))
imap.logout()
if __name__ == '__main__':
m = Mail()
m.send_email('someone#somewhere.com', 'Hello', 'Its just a test!', 'c:\\', 'test.pdf')

Email Notification for test results by using Python in Robot Framework

We are using ROBOT framework to execute automation test cases.
Could anyone please guide me to write script for e-mail notification of test results.
Note:
I have e-mail server details.
Regards,
-kranti
You can create a custom library for send email.
More details in official documentation
I did something similar, I based on this article to create the library.
an example of the function in python file:
import smtplib
from io import StringIO
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText
from email import encoders
import os
def send_mail_no_attachment(server, from_user, from_password, to, subject, text):
msg = MIMEMultipart()
msg['From'] = from_user
msg['To'] = to
msg['Subject'] = subject
msg.attach(MIMEText(text))
mailServer = smtplib.SMTP(server)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(from_user, from_password)
mailServer.sendmail(from_user, to, msg.as_string())
mailServer.close()
call the function in robot file:
*** Test Cases ***
example mail
send mail no attachment ${SMTP_SERVER} ${USER} ${PASS} ${mail} ${subject} ${text}
If you are not very expert with the robot framework, define only the function, do not define the class, and you can call this function within your algorithm as a keyword.
I use smtplib and MIMEText
import smtplib
from email.mime.text import MIMEText
class EmailClient():
def __init__(self, my_address):
self.my_address = my_address
def send(self, message, subject, user, email):
header = "Hello " + str(user) + ",\n\n"
footer = "\n\n-Your Boss"
msg = MIMEText(header + message + footer)
msg['Subject'] = subject
msg['From'] = self.my_address
msg['To'] = email
s = smtplib.SMTP('localhost')
s.sendmail(self.my_address, [email], msg.as_string())
s.quit()
EClient = EmailClient("MyEmail#University.edu")
EClient.send("This is a test Email", "Test Subject", "John Doe", "jdoe#University.edu")
you can use jenkins to run your Robot Framework Testcases. There is a auto-generated mail option in jenkins to send mail with Test results.
I have similar requirement so using python file I have achieved requirement (need to execute .py file after robot execution)
Project link and Readme.md
How to send email after test execution
Copy robotemail.py to file
Create a bat file (which executes robot command and .py file in sequence)
robot test.robot &&
python robotemail.py
Execute bat file
Email will be sent to recipients