Select to view content in your preferred language

Sending Email from Python

8651
5
Jump to solution
07-17-2012 06:27 AM
MarcCusumano
Occasional Contributor
I am trying to get this to work:

import smtplib
from smtplib import SMTP_SSL as SMTP
import datetime

HOST = "xxxxxxxx.enterprise.xxxx.com"
PORT = 25
FROM = "xxxx.xxxxxxxx@xxxx.com"
TO = ["xxxx.xxxxxxxxx@xxxx.com"]
SUBJECT = "Test"
BODY = "Success"

BODY = BODY + "!"

smtp = smtplib.SMTP(HOST,PORT)
smtp.connect(HOST, PORT)
smtp.login("xxxxxx\xxxxx", "xxxxx")
smtp.ehlo()
smtp.sendmail(FROM,TO,body)
smtp.quit()


server.set_debuglevel(0)


But I keep getting the following error:

[Errno 10054] An existing connection was forcibly closed by the remote host

Can't see anything obvious I'm doing wrong. Any ideas? Thanks.
Tags (2)
0 Kudos
1 Solution

Accepted Solutions
MarcCusumano
Occasional Contributor
I got it, was actually quite simple:

import smtplib import datetime import logging  HOST = "mailhost.xxxx.com" PORT = 25 from_addr = r"xxxx.xxxxxxx@xxxx.com" to_addr = r"xxxx.xxxxxxx@xxxx.com" subj = "ArcServer Update Script" date = datetime.datetime.now().strftime( "%d/%m/%Y %H:%M" ) message_text = "Hello\nThis is a mail from your server\n\nBye\n" msg = "From: %s\nTo: %s\nSubject: %s\nDate: %s\n\n%s" % ( from_addr, to_addr, subj, date, message_text )  try:     test = "test"         smtp = smtplib.SMTP(HOST, PORT)     smtp.sendmail(from_addr,to_addr,msg + "%s" %(test))     smtp.quit()  except Exception as e:     print e     logging.error(": %s" %(e))

View solution in original post

0 Kudos
5 Replies
MathewCoyle
Frequent Contributor
What version of python are you using? Also if you are using a domain log in you will need to send it raw, otherwise it may be interpreted as an escape.
r"xxxxxx\xxxxx"

I assume you are trying to run this on a schedule when you are not logged in? Is that why you need to specify specific log on credentials? More detail of what you are trying to accomplish and your environment would help. You would probably get a better response from a more general python forum like stack exchange since this really doesn't have anything to do with ArcGIS.
0 Kudos
MikeHunter
Occasional Contributor
I'm guessing that you either are trying to send from a company network that does not allow smtp usage, or you simply need to use tsl.  And use the email library, it handles all the ugly stuff for you.  Here's a function that does what you are trying to do.  All the args are strings except port (int), tls (boolean) and files (list of file names of attachments).  The code below is part of a larger program, so some of the imports may not be needed. 


import os, time, sys
import smtplib
from socket import gaierror

from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.utils import COMMASPACE, formatdate
from email import Encoders

from mah.wxDialogs import ibox, getfiles, ibox
import utils

def sendMail(host, user, pwd, port, subject, tls,
                            sender, to, cc, files, text, pid='0'):
    '''main email sending function'''
##    print host, user, pwd, port, tls
    msg = MIMEMultipart()
    msg['From'] = strOrBust(sender)
    msg['To'] = strOrBust(COMMASPACE.join(to))
    if cc:
        msg['Cc'] = strOrBust(COMMASPACE.join(cc))
    msg['Date'] = strOrBust(formatdate(localtime=True))
    msg['Subject'] = strOrBust(subject)

    #encode body unicode to str before sending
    msg.attach(MIMEText(strOrBust(text)))

    for file in files:
        #run with basic bag of bits, using mimetypes to try to figure out
        #file type is not worth the effort, and is not as reliable
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(file,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"'
                       % os.path.basename(file))
        msg.attach(part)

    try:
        server = smtplib.SMTP(host, port)
    except (smtplib.SMTPException, gaierror), error:
        mailer.sb.SetStatusText('Failed to send email')
        ibox(str(error) + '  Cannot connect to Server!','Failed!')
        return

    # Optional, but it gives you a nice view of the conversation
##    server.set_debuglevel(1)

    server.ehlo()
    if tls:
        server.starttls()
    server.ehlo()
    if user:
        server.login(user, pwd)
    #sendmail doesn't care about to and cc, so add them together
    #then uniqify
    toall = to + cc
    toall = uniqify(toall)

    try:
        server.sendmail(sender, toall, msg.as_string())
        if mailer:
            mailer.sb.SetStatusText('Message ' + pid +
                                        ' was successfully sent')
    except smtplib.SMTPException, error:
        if mailer:
            mailer.sb.SetStatusText('Failed to send email')
            ibox(str(error),'Failed!')
    server.close()
    return

def strOrBust(obj, encoding='utf-8'):
    '''converts unicode objects or other objects to str or returns original
        encoded to enncoding'''
    if isinstance(obj, basestring):
        if not isinstance(obj, str):
            obj = obj.encode(encoding, 'ignore')
        else:
            obj = obj.encode(encoding)
    else:
        obj = str(obj).encode(encoding)
    return obj

def uniqify(seq):
    ''' Order preserving uniqifier for list, tuple or string'''
    seen = set()
    return [x for x in seq if x not in seen and not seen.add(x)]


 

good luck
Mike
0 Kudos
MarcCusumano
Occasional Contributor
I'm running Python 2.6.5. Yes this will be part of a script that updates a File Geodatabase automatically used by ArcServer as a feature landbase. I want the email to send to myself and another individual when the process succeeds or fails.

manhunter trying to run that throws ImportError: No module named mah.wxDialogs

Thanks I appreciate the help.
0 Kudos
MikeHunter
Occasional Contributor
I'm running Python 2.6.5. Yes this will be part of a script that updates a File Geodatabase automatically used by ArcServer as a feature landbase. I want the email to send to myself and another individual when the process succeeds or fails.  

manhunter trying to run that throws   ImportError: No module named mah.wxDialogs

Thanks I appreciate the help.


Here, this should work. Like I said, I copied this from a larger program I use, so the imports and references to frames, etc. needed to be cleaned up a little.


import os, time, sys
import smtplib
from socket import gaierror

from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.utils import COMMASPACE, formatdate
from email import Encoders

def sendMail(host, user, pwd, port, subject, tls,
                            sender, to, cc, files, text, pid='0'):
    '''main email sending function'''
##    print host, user, pwd, port, tls
    msg = MIMEMultipart()
    msg['From'] = strOrBust(sender)
    msg['To'] = strOrBust(COMMASPACE.join(to))
    if cc:
        msg['Cc'] = strOrBust(COMMASPACE.join(cc))
    msg['Date'] = strOrBust(formatdate(localtime=True))
    msg['Subject'] = strOrBust(subject)

    #encode body unicode to str before sending
    msg.attach(MIMEText(strOrBust(text)))

    for file in files:
        #run with basic bag of bits, using mimetypes to try to figure out
        #file type is not worth the effort, and is not as reliable
        part = MIMEBase('application', "octet-stream")
        part.set_payload( open(file,"rb").read() )
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition', 'attachment; filename="%s"'
                       % os.path.basename(file))
        msg.attach(part)

    try:
        server = smtplib.SMTP(host, port)
    except (smtplib.SMTPException, gaierror), error:
        print str(error) + '  Cannot connect to Server!','Failed!'
        return

    # Optional, but it gives you a nice view of the conversation
##    server.set_debuglevel(1)

    server.ehlo()
    if tls:
        server.starttls()
    server.ehlo()
    if user:
        server.login(user, pwd)
    #sendmail doesn't care about to and cc, so add them together
    #then uniqify
    toall = to + cc
    toall = uniqify(toall)

    try:
        server.sendmail(sender, toall, msg.as_string())
    except smtplib.SMTPException, error:
        print str(error),'Failed!'
    server.close()
    return

def strOrBust(obj, encoding='utf-8'):
    '''converts unicode objects or other objects to str or returns original
        encoded to enncoding'''
    if isinstance(obj, basestring):
        if not isinstance(obj, str):
            obj = obj.encode(encoding, 'ignore')
        else:
            obj = obj.encode(encoding)
    else:
        obj = str(obj).encode(encoding)
    return obj

def uniqify(seq):
    ''' Order preserving uniqifier for list, tuple or string'''
    seen = set()
    return [x for x in seq if x not in seen and not seen.add(x)]



Mike
0 Kudos
MarcCusumano
Occasional Contributor
I got it, was actually quite simple:

import smtplib import datetime import logging  HOST = "mailhost.xxxx.com" PORT = 25 from_addr = r"xxxx.xxxxxxx@xxxx.com" to_addr = r"xxxx.xxxxxxx@xxxx.com" subj = "ArcServer Update Script" date = datetime.datetime.now().strftime( "%d/%m/%Y %H:%M" ) message_text = "Hello\nThis is a mail from your server\n\nBye\n" msg = "From: %s\nTo: %s\nSubject: %s\nDate: %s\n\n%s" % ( from_addr, to_addr, subj, date, message_text )  try:     test = "test"         smtp = smtplib.SMTP(HOST, PORT)     smtp.sendmail(from_addr,to_addr,msg + "%s" %(test))     smtp.quit()  except Exception as e:     print e     logging.error(": %s" %(e))
0 Kudos