indentation is causing issues while sending email in a method - python

I am trying to send an email using Pythion smtp library. I have got below code but somehow when I get an email, it doesn't have "To", "Subject" and "Body" contents as they are missing. I believe something is wrong with the way message string is constructed.
import smtplib
import socket
FROM = "from#host.com"
TO = ["to#host.com"]
def send_email():
hostname = socket.getfqdn()
text = "Hello"
subject = "Error on %s " % (hostname)
print subject
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), subject, text)
smtp_server = ""
if ".dev" not in hostname:
smtp_server = "abc.host.com"
else:
smtp_server = "pqr.host.com"
# Send the mail
server = smtplib.SMTP(smtp_server)
server.sendmail(FROM, TO, message)
server.quit()
send_email()
But when I use exact same below code, it works fine without any issues so I am sure something is wrong with my above code when I put everything in a method. I believe indentation is causing issues with the way message string is contructed or something else which I am not able to figure out.
import smtplib
import socket
SERVER = "abc.host.com"
FROM = "from#host.com"
TO = ["to#host.com"]
SUBJECT = "Test! %s " % (socket.getfqdn())
TEXT = "Testing."
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join( TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
Here is what I see with first code. If you see closely it has lot of spaces in front of each tag as compared to what gets printed out with second code:
From: from#host.com
To: to#host.com
Subject: Error on machineA
Hello
This is what I see with second code:
From: from#host.com
To: to#host.com
Subject: Test! machineA
Testing.
How do I fix this in first code when I am putting it in a method?
Update:
I tried with below code but it gives me error about indentation is wrong on print message.
import smtplib
import socket
FROM = "from#host.com"
TO = ["to#host.com"]
def send_email():
hostname = socket.getfqdn()
text = "Hello"
subject = "Error on %s " % (hostname)
print subject
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), subject, text)
print message
smtp_server = ""
if ".dev" not in hostname:
smtp_server = "abc.host.com"
else:
smtp_server = "pqr.host.com"
# Send the mail
server = smtplib.SMTP(smtp_server)
server.sendmail(FROM, TO, message)
server.quit()
send_email()

Use the stdlib emailpackage to help you building your mail as correct SMTP payloads (headers, encoding, parts, ...). https://docs.python.org/3/library/email.html#module-email
There are tons of examples in the standard doc or in stackoverflow.

You are allowed to remove the indents:
def send_email():
# stuff ...
# Prepare actual message
message = """\
From: %s
- other stuff...
""" % (FROM, ", ".join(TO), subject, text)
smtp_server = ""
# more stuff...
server.sendmail(FROM, TO, message)
server.quit()
Also, not sure you need the back slash?
message = ''' < == no backslash
stuff
'''

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 code behaves differently when in a loop

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

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()

unable to send email using python

What am I doing wrong? Should be so simple.After I execute - nothing happens, no errors, no email. Nothing.
I am using Jupyter.
def send_email(user, pwd, recipient, subject, body):
import smtplib
gmail_user = 'email#email.com'
gmail_pwd = 'pass'
FROM = 'email#email.com'
TO = 'email#email.com'
SUBJECT = 'Test'
TEXT = 'Hello, this is test email'
# Prepare actual message
message = """From: %s\nTo: %s\nSubject: %s\n\n%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pwd)
server.sendmail(FROM, TO, message)
server.close()
print ('successfully sent the mail')
except:
print ("failed to send mail")
It is only function definiton. You have to execut it like
send_email("me#gmai.com", "MyPaSwOrD", "you#gmail.com", "Money for you", "Hi")
But your code will not use this data because it has hardcoded values inside.

Sending emails in python via loop

Is there a way to send emails to all the email addresses in the database via for loops? I'm not very sure on for loops and needs help.
I followed this page for email sample. SQL statement would be select email from table name
import smtplib
SERVER = "localhost"
FROM = "sender#example.com"
TO = ["user#example.com"]
SUBJECT = "Hello!"
TEXT = "This message was sent with Python's smtplib."
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
You will have to download and import the correct Database interface. (MySQL or SQL Server etc.)
Then do something like this:
import smtplib
import MySQLdb
SERVER = "localhost"
FROM = "sender#example.com"
TO = ["user#example.com","another#user.com","many#users.com"]
#SQL data access part
db = MySQLdb.connect(host='localhost', user='root', passwd='$$', db='emaildatabase')
cursor = db.cursor()
cursor.execute('select email from tablename where email is not null')
db.commit()
rows = cursor.fetchall()
for item in rows:
TO.append(item)
SUBJECT = "Hello!"
TEXT = "This message was sent with Python's smtplib."
# Prepare actual message
message = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()
Let me know if you don't understand.

Categories