Using function to send gmails via python - python

Below are 2 code blocks. The first will send a message to gmail with the correct subject and sender. However, when I put the first code into a function, the email loses the sender and subject info.
Why is this and how do I fix it?
I would like to be able to call this function from other python scripts to notify me when my job is complete. The function works and runs without error, and the email makes it to my inbox, but I lose the sender info and more importantly, the subject heading.
1st code that runs as expected:
import smtplib
gmail_user = 'name#domain.com'
gmail_password = 'password'
sent_from = gmail_user
to = ['recipient#domain.com']
subject = "job complete"
body = "python script " + str(name) + " has finished"
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
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()
2nd code that loses subject and sender info:
def mailer(subject, body):
import smtplib
gmail_user = 'name#domain.com'
gmail_password = 'password'
sent_from = gmail_user
to = ['recipient#domain.com']
subject = subject
body = body
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
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()
subject = "job complete"
body = "python script " + str(name) + " has finished"
mailer(subject, body)

It's most likely a line ending issue. Each mail headers is required to end with CRLF (\r\n). The original message string may have contained the correct endings (invisible in the editor) which were subsequently lost during copy/paste to the function version. To ensure that each line is ended correctly, try expressing each as a separate string and joining them with \r\n.
email_text = '\r\n'.join([
'From: %s' % sent_from,
'To: %s' % ', '.join(to),
'Subject: %s' % subject',
'', # Blank line to signal end of headers
body
])

Related

Python: How to pass email text body to Office365 Email

Trying to make the script below work for office365. Sends out an email but I cannot get the script to recognize the actual email text body (only the Subject line being sent). Below script worked for gmail. Any ideas where I need to modify?
Thanks!
import smtplib, ssl
port = 587
smtp_server = "smtp.office365.com"
sender_email = "me#email.com"
receiver_email = {'User1': 'user1#email.com'}
password = "password"
subject = input('Enter the subject line: ')
message = input('Enter the message: ')
email = """\
Subject: %s
%s
""" % (subject, message)
for key, value in receiver_email.items():
context = ssl.create_default_context()
with smtplib.SMTP(smtp_server, port) as server:
server.ehlo() # Can be omitted
server.starttls(context=context)
server.ehlo() # Can be omitted
server.login(sender_email, password)
server.sendmail(sender_email, value, email)
server.quit()
was missing a "\n" in the email object. It now works.
email = """\
Subject: %s\n
%s
""" % (subject, message)

how to catch error in finally block in python

I could see several topics on try - catch but doesnt seem to discuss errors if any from finally block itself. I found that the error is not handled if it is in finally block. What would be the ideal way to manage finally?
For eg. below is a mail function. if there is any error in try block, finally will execute the quit method which itself is not initiated so an unhandled error occurs. So is it better to ensure there is no errors occur in finally block?
def send_email(ldap, email_address, password, msg):
try:
message = MIMEMultipart('alternative')
message['To'] = email.utils.formataddr(('Recipient', '%s#abc.com'%email_address))
message['From'] = email.utils.formataddr(('Author', '%s#abc.com'%email_address))
message['Subject'] = 'Sample subject'
text = "%s"%msg
html = MIMEText('<html><head></head><h2>data</h2><body><p>%s</p></body></html>'%msg,'html')
message.attach(html)
server = smtplib.SMTP(host="ip",port=0)
server.set_debuglevel(True)
# identify ourselves, prompting server for supported features
server.ehlo()
if server.has_extn('STARTTLS'):
server.starttls()
server.ehlo()
server.login(ldap, password)
print "%s#abc.com, %s#abc.com, %s "%(email_address,email_address,message.as_string())
server.sendmail('%s#abc.com'%email_address, "%s#abc.com"%email_address, message.as_string())
finally:
server.quit()
Dont put a bunch of code (doing different things) into one try/except block, but you can easily add an if/else condition in your finally block:
def send_email(ldap, email_address, password, msg):
server = None #make sure server variable is always defined.
try:
...
server = smtplib.SMTP(...)
...
finally:
if server and isinstance(x, smtplib.SMTP):
server.quit()
Since your finally block is only used to ensure the server connection is properly closed whatever, the obvious answer is to only wrap the relevant part in the try block:
def send_email(ldap, email_address, password, msg):
message = MIMEMultipart('alternative')
message['To'] = email.utils.formataddr(('Recipient', '%s#abc.com'%email_address))
message['From'] = email.utils.formataddr(('Author', '%s#abc.com'%email_address))
message['Subject'] = 'Sample subject'
text = "%s"%msg
html = MIMEText('<html><head></head><h2>data</h2><body><p>%s</p></body></html>'%msg,'html')
message.attach(html)
server = smtplib.SMTP(host="ip",port=0)
# now you can start the try block:
try:
server.set_debuglevel(True)
# identify ourselves, prompting server for supported features
server.ehlo()
if server.has_extn('STARTTLS'):
server.starttls()
server.ehlo()
server.login(ldap, password)
print "%s#abc.com, %s#abc.com, %s "%(email_address,email_address,message.as_string())
server.sendmail('%s#abc.com'%email_address, "%s#abc.com"%email_address, message.as_string())
finally:
server.quit()
A still better solution would be to split this code in distinct functions each with a single well-defined responsability - preparing the message, getting a connection to the server etc, ie:
def prepare_message(sender, recipient, subject, msg):
message = MIMEMultipart('alternative')
message['To'] = email.utils.formataddr(('Recipient', recipient))
message['From'] = email.utils.formataddr(('Author', sender))
message['Subject'] = subject
#text = "%s" % msg # this one is useless
html = MIMEText("""
<html>
<head></head>
<body>
<h2>data</h2>
<p>%s</p>
</body>
</html>""" % msg,
'html'
)
message.attach(html)
return message
def connect(ldap, password):
server = smtplib.SMTP(host="ip",port=0)
server.set_debuglevel(True)
# identify ourselves, prompting server for supported features
server.ehlo()
if server.has_extn('STARTTLS'):
server.starttls()
server.ehlo()
server.login(ldap, password)
return server
def send_email(ldap, email_address, password, msg):
sender = recipient = "%s#abc.com" % email_address
message = prepare_message(sender, recipient, 'Sample subject', msg)
server = connect(ldap, password)
try:
server.sendmail(sender, recipient, message.as_string())
finally:
server.quit()

SMTP AUTH extension not supported by server in python

I'm using the following def to send email based on status ,
def sendMail(fbase, status):
server = smtplib.SMTP(config["global"]["smtp_server"], config["global"]["smtp_port"])
server.login(config["global"]["smtp_user"],config["global"]["smtp_pass"])
server.ehlo()
server.starttls()
from_addr = config["global"]["smtp_from"]
if status == "Success":
subject = "%s Uploaded sucessfully" % fbase
msg = "\nHi,\n Video file - %s - uploaded successfully \n Thanks \n Online Team" % fbase
to_addr_list = config["global"]["smtp_to_success"]
else:
subject = "%s Failed to upload" % fbase
msg = "\n Hi!\n Failed to upload %s \n Please check the log file immediatly \n Thanks" % fbase
to_addr_list = config["global"]["smtp_to_failed"]
header = 'From: %s\n' % from_addr
header += 'To: %s\n' % ','.join(to_addr_list)
header += 'Subject: %s\n\n' % subject
message = header + msg
server.sendmail(from_addr, to_addr_list, message)
server.quit()
logger.info("Mail send for status: %s" %(status))
i start getting the following error after Ad admins upgrade the exchange
raise ("SMTP AUTH extension not supported by server.")
SMTPException: SMTP ASMTPExceptionUTH extension not supported by server.
I added
server.ehlo()
server.starttls()
and still getting the same error ,
any advise here
Perform the login step after you've started TLS.
def sendMail(fbase, status):
server = smtplib.SMTP(config["global"]["smtp_server"], config["global"]["smtp_port"])
server.ehlo()
server.starttls()
server.login(config["global"]["smtp_user"],config["global"]["smtp_pass"])
....

Pass Print messages in Python to email

I've written a python script that has several print statements in it. I'd like to pass these print statements to an email that the script will send me after it has finished running. Is this possible?
Below is my attempt, it errors out at the deleted =
import arcpy, os
arcpy.DeleteRows_management(r"C:\GIS_Work\StreetsTesting\Lake George.shp")
deleted = print "The rows have been deleted from Lake George"
# Send Email when script is complete
SERVER = "my.mailserver.com"
FROM = "from#email.com>"
TO = "to#email.com>"
SUBJECT = "The Script Has Completed"
MSG = deleted
# Prepare actual message
MESSAGE = """\
From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, MSG)
# Send the mail
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, MESSAGE)
server.quit()

Sending Verizon SMS message via Python and smtplib

I can make smtplib send to other email addresses, but for some reason it is not delivering to my phone.
import smtplib
msg = 'test'
server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()
server.login("<username>","<password>")
server.sendmail(username, "<number>#vtext.com", msg)
server.quit()
The message sends successfully when the address is a gmail account, and sending a message to the phone using the native gmail interface works perfectly. What is different with SMS message numbers?
Note: using set_debuglevel() I can tell that smtplib believes the message to be successful, so I am fairly confident the discrepancy has something to do with the behavior of vtext numbers.
The email is being rejected because it doesn't look an email (there aren't any To From or Subject fields)
This works:
import smtplib
username = "account#gmail.com"
password = "password"
vtext = "1112223333#vtext.com"
message = "this is the message to be sent"
msg = """From: %s
To: %s
Subject: text-message
%s""" % (username, vtext, message)
server = smtplib.SMTP('smtp.gmail.com',587)
server.starttls()
server.login(username,password)
server.sendmail(username, vtext, msg)
server.quit()
The accepted answer didn't work for me with Python 3.3.3. I had to use MIMEText also:
import smtplib
from email.mime.text import MIMEText
username = "account#gmail.com"
password = "password"
vtext = "1112223333#vtext.com"
message = "this is the message to be sent"
msg = MIMEText("""From: %s
To: %s
Subject: text-message
%s""" % (username, vtext, message))
server = smtplib.SMTP('smtp.gmail.com',587)
# server.starttls()
server.login(username,password)
server.sendmail(username, vtext, msg.as_string())
server.quit()

Categories

Resources