Python2.7 sending mail, why msg['To'] stay empty? - python

I am sending multiple recipients mail with a python script, and it works, but in the "To" in the mail, the field is empty. On every mail provider I tried.
Here is my code :
def send_mail(self, server, send_from, subject, attach, foo=None, bar=None)
msg = MIMEMultipart()
msg['From'] = send_from
msg['Subject'] = subject
body = u"""<html> My Body </html>"""
#Attach file pdf
msg.attach(MIMEText(body, 'html', 'utf-8'))
filename = 'fname.pdf'
attachment = open(attach, "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)
text = msg.as_string()
if foo != None and bar != None:
recipients = ["a#b.fr", "b#b.fr"]
msg['To'] = ", ".join(recipients)
server.sendmail(send_from, recipients, text)
else:
msg['To'] = "c#b.fr"
server.sendmail(send_from, msg['To'], text)
sleep(1)
msg['To'] should be the "To" in my mail but it stays empty. (Even in the "else" with only one recipient). I can't find any help about it on existing question, so I come to ask for your help about that.

As per the documentation, the second parameter is a LIST of recipients. You need to change your line
server.sendmail(send_from, msg['To'], text)
to
server.sendmail(send_from, [msg['To']], text)

Finally found out:
text = msg.as_string() should be done after the assignement to msg['To'] So it will appear in my if and else block juste before the server.sendmail(send_from, msg['To'], text) since all information written in the mail, even 'To', and 'From' are in the third argument text .

Related

Email sending without attachment - Python 3.8

I want to send a .txt file attached to the mail in Python.
Currently the mail is received but without any attachment.
Code bellow
I've sent emails in PHP but Python is completely new to me
The code doesn't return any errors, it simply doesn't send the attachment with the email
with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
server = smtplib.SMTP('smtp.gmail.com', 587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
msg = MIMEMultipart()
smtp.login(EMAIL_ADRESS, EMAIL_PASSWORD)
subject = 'Log Register'
filename = 'logs-to-h4wtsh0wt.txt'
attachment = open(filename, 'rb')
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= "+filename)
msg.attach(part)
msg = f'Subject: {subject}\n\n{Body}'
smtp.sendmail(EMAIL_ADRESS,EMAIL_ADRESS, msg)
snakecharmerb is right. You are indeed overriding the message object and therefore losing everything you add before that point.
You can instead set the subject like this:
msg['Subject'] = "Subject of the Mail"
# string to store the body of the mail
body = "Body_of_the_mail"
# attach the body with the msg instance
msg.attach(MIMEText(body, 'plain'))
Because you are attaching a file you will also need to convert the multipart message into a string before sending:
text = msg.as_string()
smtp.sendmail(fromaddr, toaddr, text)
When you created msg with MIMEMultipart() it generated the message object structure for you as per RFC2822 which also gives you FROM, TO, etc.
The msg object also has a bunch of functions you can run outlined in its docs

Sending an email with attachment

I am trying to write a function that send an email with an attached file. At the moment, it send an email but without attachment. Can you someone comment?
msg = MIMEMultipart()
msg['From'] = my email
msg['To'] = client email address
msg['Subject'] = subject
body = content
msg.attach(MIMEText(body, 'plain'))
##### Load the address of the file which should be attached*********************************
filename = filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("Text
files","*.txt"),("all files","*.*")))
Myfile = open(filename)
attachment = MIMEText(Myfile.read())
attachment.add_header('Content-Disposition', 'attachment', filename=filename)
msg.attach(attachment)
mail = smtplib.SMTP('smtp.gmail.com', 587)
msg = f'Subject: {subject}\n\n{content}'
mail.ehlo()
mail.starttls()
mail.login('My email address', 'password')
mail.sendmail('client email', My email address, msg)
mail.close()
Thank you all in advance
First, as mentioned in my comment, you're overwriting msg here:
msg = f'Subject: {subject}\n\n{content}'
At this point, the MIMEMultipart object msg used to point to is destroyed, and you'll send only that new string. No wonder why there's no attachment: this string obviously doesn't have an attachment.
Now, you should really be using the new API of the email module, as shown in the documentation. But since you're already using the legacy API (the MIMEMultipart class, for example), you'll need to convert msg to a string, as shown here:
# This is copied straight from the last link
msg = MIMEMultipart('alternative')
msg['Subject'] = "Link"
msg['From'] = me
msg['To'] = you
...
part1 = MIMEText(text, 'plain') # example attachment
# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
mail.sendmail(
me, you,
msg.as_string() # CONVERT TO STRING
)

Send email in python using subprocess

I am trying to send an email with an attachment from CentOS using python. I've below code working fine on windows machine but, when I run this code it gives me an error
(110, 'Connection timed out')
def send_email(self):
print("Sending an email...")
try:
sender = 'xxxxx#domain.com'
receiver = 'yyyyy#domain.com'
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = receiver
msg['Subject'] = self.new_folder_name + 'Portal Automation testing results'
body = 'Hi, \n\n This is my email body. \n\n Thanks.'
msg.attach(MIMEText(body, 'plain'))
filename = self.zip_file_name
attachment = open(filename, 'rb')
part = MIMEBase('application', 'octet-stream')
part.set_payload((attachment).read())
# part.set_payload((attachment).read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', "attachment; filename= " + filename)
msg.attach(part)
server = smtplib.SMTP('mail.xxxxx.com', 587)
server.starttls()
server.login(sender, "mypassword")
text = msg.as_string()
server.sendmail(sender, receiver, text)
server.quit()
print('.......')
print("Email sent.")
print("-------------------------------------------")
except Exception as e:
print('Email can not be sent. Error ====>', e)
So, I've used subprocess and it does send an email with attachment but I can't modify the message body as I want. Here is my code,
def send_email(self):
print('Sending email to xxxxxxx#domain.com')
body = 'This is email body'
file_path = '/home/Path/to/file/{}/{}'.format(self.new_folder_name, self.zip_file_name)
send_email_1 = 'echo {} | mail -s "Email testing" -a {} xxxxle#nuance.com'.format(body, file_path)
send = subprocess.call(send_email_1, shell=True)
Email Output: Hi, /n /nThis is a sample email boby. /n /n Regards
I need help with 1st code sample to make it work on CentOS or 2nd code sample where I can format my email body.
Any help is really appreciated.

MIMEMultipart edit msg['To'] recipients

I have a loop that iterates through a list of addresses and sends mail to each.
def send_mail(self, user_name, smtp_host, smtp_user, smtp_pass, smtp_port):
s = smtplib.SMTP_SSL(smtp_host[0],smtp_port[0])
s.login(smtp_user[0],smtp_pass[0])
msg = MIMEMultipart()
msg.attach(MIMEText(self.message))
msg['From'] = user_name[0]
msg['Subject'] = self.subject
for f in self.attachment_list:
part = MIMEBase('application', "octet-stream")
part.set_payload(open('temp/'+f,"rb").read())
encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="{0}"'.format(os.path.basename(f)))
msg.attach(part)
for i,address in enumerate(Sheet.email_list):
print("Send email: " + address)
msg['To'] = address
s.sendmail(smtp_user[0], address, msg.as_string())
s.quit()
print("SMTP connection closed")
The code runs fine and sends an email to each address. However, when I view the email in Mail Application it lists: "To: " with each address. I intend for it to only list the recipient who is receiving the emails address. I played around with the code and I have determined that the issue is coming from msg['To']. I have tried to adjust it many ways, but I do not know how to make it send with only the one recipients address displayed.
msg['To'] addresses
I found the answer. I needed to replace the To header with each iteration.
if 'To' in msg:
msg.replace_header('To', address)
else:
msg['To'] = address

How to send email with ZIP attachments from web server in Python

I have a question about sending an email with ZIP attachments in Python. Here is how I am doing it:
def send_mail(send_from, send_to, subject, text, files=[], server="localhost"):
assert type(send_to)==list
assert type(files)==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:
remotezip = urllib2.urlopen(f)
#zipinmemory = io.BytesIO(remotezip.read())
#zip = zipfile.ZipFile(zipinmemory)
part = MIMEBase('application', 'octet-stream')
part.set_payload( remotezip.read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(f))
msg.attach(part)
smtp = smtplib.SMTP('smtp.gmail.com:587')
smtp.starttls()
smtp.login('username','password')
smtp.sendmail(send_from, send_to, msg.as_string())
smtp.close()
As I have my ZIP file hosted on my web server, I am reading it using URLOpen.
This code successfully sends an email with the attachment. But the ZIP file is always 0KB. Am sure there is some issue in reading the file.
Please let me know. Thanks for your help!

Categories

Resources