Python code behaves differently when in a loop - python

I wanted to try to send emails with python and found some barebone code to do so online
import smtplib
gmail_user = 'myaddress#gmail.com'
gmail_pw = 'myPassword'
sent_from = gmail_user
to = ['mailAdrr1#domain.com', 'mailAdrr2#domain.com']
subject = 'Some Subject'
body = 'Some body'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
smtp_server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
smtp_server.ehlo()
smtp_server.login(gmail_user, gmail_pw)
smtp_server.sendmail(sent_from, to, email_text)
smtp_server.close()
print("Success")
except Exception as ex:
print("Error: ", ex)
Now I wanted to send an email to every target separately so I added a foreach loop within the code. This resulted in the Email headers being messed up and all the headers were interpreted as the From header. Although when I printed them out, they looked fine
After being very confused as to why this happens I decided to try to wrap the entire code in a for loop with one iteration which - according to my understanding - should change nothing at all. But in fact it does produce the same issue as described above. This is how I wrapped the code in a loop:
import smtplib
for i in range(1):
gmail_user = 'myaddress#gmail.com'
gmail_pw = 'myPassword'
sent_from = gmail_user
to = ['mailAdrr1#domain.com', 'mailAdrr2#domain.com']
subject = 'Some Subject'
body = 'Some body'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
smtp_server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
smtp_server.ehlo()
smtp_server.login(gmail_user, gmail_pw)
smtp_server.sendmail(sent_from, to, email_text)
smtp_server.close()
print("Success")
except Exception as ex:
print("Error: ", ex)
Why does a for loop with one iteration change anything about the workings of the code if literally everything is done within it?

this is the code you would want I suspect:
import smtplib
gmail_user = 'MyEmail#gmail.com'
gmail_pw = 'MyPassword'
sent_from = gmail_user
to = ['PersonA#gmail.com', 'PersonB#gmail.com']
subject = 'Some Subject for multiple people'
body = 'Some body for a few'
smtp_server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
smtp_server.ehlo()
smtp_server.login(gmail_user, gmail_pw)
for email in to:
email_text = 'Subject:{}\n\n{}'.format(subject, body)
try:
smtp_server.sendmail(sent_from, email, email_text)
print("Success")
except Exception as ex:
print("Error: ", ex)
smtp_server.close()
You had 2 main problems with how you were approaching it. For whatever reason, if you logged in inside of a loop, it would fail. I've moved this to the start and called close() at the end to prevent logging in multiple times as well.
The second issue you had was to do with how you were formatting the email data itself. I used this answers example to assist with making this work, so see this for more: How to add a subject to an email being sent with gmail?
Hopefully, this solves your issue!
Many thanks, GhostDog

Related

Error when executing email send code in Python function

I wrote a code to send a confirmation email with Python and it works, but when I put it in the function, sending the code has a problem. Please help me.
code :
import smtplib
import random
verify_code=str(random.randint(1111,9999))
sent_from = 'code#r*****'
password='*******'
to = ['re******#gmail.com']
subject = 'verify code'
body = ('your code is :'+str(code))
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
smtp_server = smtplib.SMTP_SSL('mx2.ta*******.com', 465)
smtp_server.ehlo()
smtp_server.login(sent_from, password)
smtp_server.sendmail(sent_from, to, email_text)
smtp_server.close()
print ("Email sent successfully!")
and When I put in the function :
def mail(code):
import smtplib
import random
code=str(random.randint(1111,9999))
sent_from = 'code#r****'
password='*******'
to = ['re*******#gmail.com']
subject = 'verify code'
body = ('your code is :'+str(code))
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
smtp_server = smtplib.SMTP_SSL('mx2.tal*****.com', 465)
smtp_server.ehlo()
smtp_server.login(sent_from, password)
smtp_server.sendmail(sent_from, to, email_text)
smtp_server.close()
print ("Email sent successfully!")
Error while executing the function:
This message was created automatically by mail delivery software.
A message that you sent could not be delivered to one or more of its
recipients. This is a permanent error. The following address(es) failed:
reza*****#gmail.com
host gmail-smtp-in.l.google.com [108.177.126.27]
SMTP error from remote mail server after end of data:
550-5.7.1 [185.51..] Our system has detected that this message is not RFC
550-5.7.1 5322 compliant:
550-5.7.1 'From' header is missing.
550-5.7.1 To reduce the amount of spam sent to Gmail, this message has been
550-5.7.1 blocked. Please visit
550-5.7.1 https://support.google.com/mail/?p=RfcMessageNonCompliant
550 5.7.1 and review RFC 5322 specifications for more information.
Attempt 1 : ratelimit number of emails sent
You are probably sending too many emails at once. Try waiting a few seconds between each email. Since you are using a Gmail account to send emails, you might want to have a look at the email quotas imposed by Google.
Also if you are calling your function in a loop, you are sending multiple emails to the same recipient. The parameter of your function should the email of the recipient instead of code.
import smtplib
import random
import time
def mail(recipient):
code = str(random.randint(1111, 9999))
sent_from = 'code#r****'
password = '*******'
to = [recipient]
subject = 'verify code'
body = ('your code is :'+str(code))
email_text = """From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
smtp_server = smtplib.SMTP_SSL('mx2.tal*****.com', 465)
smtp_server.ehlo()
smtp_server.login(sent_from, password)
smtp_server.sendmail(sent_from, to, email_text)
smtp_server.close()
print("Email sent successfully!")
recipient_list = ['aaa#gmail.com', 'bbb#gmail.com']
for recipient in recipient_list:
mail(recipient)
time.sleep(1) # wait 1s before sending next email
Attempt 2 : use CRLF character directly in email_text
The format of the From field field as required by RFC 5322 is :
"From:" mailbox-list CRLF
In Python the CRLF character is \r\n so lets use it directly in email_text as shown below :
email_text = (
"""From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s"""
% (sent_from, ", ".join(to), subject, body))
This ensures that the correct line breaks are inserted at the right place. (we don't have to rely on the line breaks inserted by Enter key)
full code with function :
import smtplib
import random
def mail():
code = str(random.randint(1111, 9999))
sent_from = 'code#r****'
password = '*******'
to = ['re*******#gmail.com']
subject = 'verify code'
body = ('your code is :'+str(code))
email_text = (
"""From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s"""
% (sent_from, ", ".join(to), subject, body))
print(email_text)
smtp_server = smtplib.SMTP_SSL('mx2.tal*****.com', 465)
smtp_server.ehlo()
smtp_server.login(sent_from, password)
smtp_server.sendmail(sent_from, to, email_text)
smtp_server.close()
print("Email sent successfully!")
mail()

Python send simple mail

Im trying to write a simple script which has to send a simple email in some cases.
I have the following script which works well if im using just only this script.
import smtplib
mail_user = '123#123.com'
mail_password = 'password'
sent_from = mail_user
to = ['reciever#address.com']
subject = 'My subject'
body = 'Hello mail.'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
server = smtplib.SMTP_SSL('mail.123.com', 465)
server.ehlo()
server.login(mail_user, mail_password)
server.sendmail(sent_from, to, email_text)
server.close()
print 'Email sent!'
except:
print 'Something went wrong...'
The problem is when im trying to put this code into a def and call from outside the e-mail is missing headers, i mean the email is arriving without sender and without subject. Sender empty and subject empty, but i have only the body.
I also can not get the mail when im sending to another domain, but i think this is because the another domain is rejecting the mail without headers, when using only the script the mail arrives also to other domains.
import smtplib
def sendMail():
mail_user = '123#123.com'
mail_password = 'password'
sent_from = mail_user
to = ['reciever#address.com']
subject = 'My subject'
body = 'Hello mail.'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
server = smtplib.SMTP_SSL('mail.123.com', 465)
server.ehlo()
server.login(mail_user, mail_password)
server.sendmail(sent_from, to, email_text)
server.close()
print 'Email sent!'
except:
print 'Something went wrong...'
sendMail();
What is the diffenerece when i put this code into a def? Why this happening? What im doing wrong?
Thanks for help.
In your function version, your email headers have become indented
email_text = """\
From: %s
To: %s
Subject: %s
%s
...
In this string, the To: and Subject: are now indented.
def sendMail():
call it with:
sendMail()
not SendMail()

Hey I want to send email to more than one person with python

Hey i want to send an email to a bunch of people but for some reason even if the output of print is more than one email the program sending the email only to first person of the text what can i do ?
# Import Python Packages
import smtplib
# Set Global Variables
gmail_user = 'your#gmail.com'
gmail_password = 'password'
# Create Email
mail_from = gmail_user
for i in range(2):
with open('C:\\email.txt', 'r', encoding="utf8") as f
mail_to = f.read().rstrip()
mail_subject = 'subject'
mail_message_body = 'body'
mail_message = '''\
From: %s
To: %s
Subject: %s
%s
''' % (mail_from, mail_to, mail_subject, mail_message_body)
# Sent Email
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login(gmail_user, gmail_password)
server.sendmail(mail_from, mail_to, mail_message)
print(mail_to)
server.close()
Send_to must be a string object having addresses separated by ", ".
example :
send_to='xyz1#gmail.com,hhdasn#yahoo.com'
The line that performs sending of email is server.sendmail(mail_from, mail_to, mail_message). You are calling it once. You can check it by placing print(mail_to) statement next to it.
You need to call sendmail in loop if you want to send email multiple times.

Email function does not work after put in a class [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
So basically I copy and pasted an email sending python script which works. This is the code:
import smtplib
gmail_user = 'email#email.com'
gmail_password = 'P#ssword!'
sent_from = gmail_user
to = ['bill#gmail.com']
subject = 'OMG Super Important Message'
body = 'Hey, whats up?\n\n- You'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_password)
server.sendmail(sent_from, to, email_text)
server.close()
print ('Email sent!')
except:
print ('Something went wrong...')
The result is as perfectly described:
Unfortunately, I put the code within a class to execute as a function from another main function. Code is as below:
import smtplib
class EmailSending():
def doneEmail(self):
gmail_user = 'email#email.com'
gmail_password = 'P#ssword!'
sent_from = gmail_user
to = ['bill#gmail.com']
subject = 'OMG Super Important Message'
body = 'Hey, whats up?\n\n- You'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_password)
server.sendmail(sent_from, to, email_text)
server.close()
print('Email sent!')
except:
print('Something went wrong...')
ef = EmailSending()
ef.doneEmail()
The only code that changed is that it is now in a class function.
But when calling it, it returns a different result, shown below
The email still sends to my email but everything else is out. Can anyone help me out? Thx
You have added spaces at the beginnings of the lines containing From: and so on. Remove them:
class EmailSending():
def doneEmail(self):
gmail_user = 'email#email.com'
gmail_password = 'P#ssword!'
sent_from = gmail_user
to = ['bill#gmail.com']
subject = 'OMG Super Important Message'
body = 'Hey, whats up?\n\n- You'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_password)
server.sendmail(sent_from, to, email_text)
server.close()
print('Email sent!')
except:
print('Something went wrong...')
ef = EmailSending()
ef.doneEmail()

Sending an Email with Python Issue

I have this code and I cannot seem to get it to work. When I run it, the script doesn't finish in IDLE unless I kill it manually. I have looked all over and rewritten the code a few times, and no luck.
import smtplib
SMTP_SERVER = 'smtp.gmail.com'
SMTP_PORT = 587
sender = 'abc#gmail.com'
password = '123'
recipient = 'cba#gmail.com'
subject = 'Test Results'
body = """** AUTOMATED EMAIL ** \r\n Following are
the test results: \r\n"""
headers = ["From: " + sender,
"Subject: " + subject,
"To: " + recipient]
headers = "\r\n".join(headers)
try:
session = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
session.ehlo()
session.starttls()
session.ehlo()
session.login(sender, password)
session.sendmail(sender, recipient, headers + "\r\n\r\n" + body)
except smtplib.SMTPException:
print "Error: Unable to send email."
session.quit()
Not sure why you're using ehlo; contrary to popular opinion, it's not actually required so long as you set the headers correctly. Here's a tested and working script -- it works on *nix and OSX. Since you're using Windows though, we need to troubleshoot further.
import smtplib, sys
def notify(fromname, fromemail, toname, toemail, subject, body, password):
fromaddr = fromname+" <"+fromemail+">"
toaddrs = [toname+" <"+toemail+">"]
msg = "From: "+fromaddr+"\nTo: "+toemail+"\nMIME-Version: 1.0\nContent-type: text/plain\nSubject: "+subject+"\n"+body
# Credentials (if needed)
username = fromemail
password = password
# The actual mail send
try:
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
print "success"
except smtplib.SMTPException:
print "failure"
fromname = "Your Name"
fromemail = "yourgmailaccount#gmail.com"
toname = "Recipient"
toemail = "recipient#other.com"
subject = "Test Mail"
body = "Body....."
notify(fromname, fromemail, toname, toemail, subject, body, password)

Categories