By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,190 Members | 777 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,190 IT Pros & Developers. It's quick & easy.

Monitoring number of smtp bytes sent through python e-mail socket

P: 1
Hi,

I have a small python program with e-mail capabilities that I have pieced together from code snippets found on the internet.

The program uses the smtplib module to successfully send an e-mail with an attachment.

I want to give users an indication of the percentage of the e-mail that has already been sent so as to avoid frustration when dealing with large attachments or a slow smtp server. But the smtplib module doesn't seem to provide access to the number of bytes that have already been sent.

Can anyone help, or provide a working example of sending an e-mail attachment using basic python sockets whilst having access to the number of bytes that have already been sent through the socket?

Many thanks.

William Connery


Expand|Select|Wrap|Line Numbers
  1. #!/usr/bin/python
  2.  
  3. import wx
  4. import smtplib
  5. from email import Encoders
  6. from email.MIMEMultipart import MIMEMultipart
  7. from email.Utils import COMMASPACE, formatdate
  8. from email.MIMEBase import MIMEBase
  9. from email.MIMEText import MIMEText
  10. import os
  11.  
  12. # set a few variables to make testing less tedious
  13.  
  14. # you need to set your smtp server domain name
  15. smtp_server = 'smtp.your_isp_domain.com'
  16.  
  17. toemail = 'toemail@somedomain.org'
  18. fromemail = 'fromemail@anotherdomain.org'
  19. subject = 'Testing python smtplib module'
  20. emailmsg = 'How do I determine the number of bytes that have been ' +\
  21. 'forwarded whilst the e-mail is being sent?\n\nSending large (or many) ' +\
  22. 'attachments may take some time, and I\'d like to use a gauge ' +\
  23. 'control to give users an indication of the percentage of ' +\
  24. 'the e-mail that has already been sent.\n\nThe smtplib module relies ' +\
  25. 'on sockets, but I don\'t know how to use python sockets to ' +\
  26. 'send an e-mail with attachments and concurrently monitor the ' +\
  27. 'number of bytes that have already been sent.\n\nHelp !'
  28.  
  29. # attachment file
  30. attachment = 'C:\\Documents and Settings\\-\\Desktop\\test.zip'
  31. #attachment = '/home/user1/Desktop/test.zip'
  32.  
  33.  
  34. # variable to hold bytes that have been sent
  35. bytes_sent = 0
  36.  
  37.  
  38.  
  39.  
  40. class MainFrame(wx.Frame):
  41.     def __init__(self, *args, **kwargs):
  42.         wx.Frame.__init__(self, *args, **kwargs)
  43.         self.SetSize(wx.Size(750,550))
  44.         self.SetTitle('Monitoring the number of bytes sent during ' +\
  45.         'a python e-mail send  -  How ?')
  46.  
  47.         panel = wx.Panel(self)
  48.  
  49.         vertsizer = wx.BoxSizer(wx.VERTICAL)
  50.  
  51.         flexsizer = wx.FlexGridSizer(rows=8, cols=2, hgap=10, vgap=10)
  52.         flexsizer.AddGrowableCol(1)
  53.         flexsizer.AddGrowableRow(4)
  54.  
  55.         tolabel = wx.StaticText(panel, -1, "To E-mail Address:")
  56.         flexsizer.Add(tolabel,0,wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
  57.         self.toemailaddress = wx.TextCtrl(panel)
  58.         flexsizer.Add(self.toemailaddress,0,wx.EXPAND)
  59.  
  60.         fromlabel = wx.StaticText(panel, -1, "From E-mail Address:")
  61.         flexsizer.Add(fromlabel,0,wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
  62.         self.fromemailaddress = wx.TextCtrl(panel)
  63.         flexsizer.Add(self.fromemailaddress,0,wx.EXPAND)
  64.  
  65.         attachmentbutton = wx.Button(panel, 1001, "File Attachment")
  66.         attachmentbutton.Bind(wx.EVT_BUTTON, self.SelectAttachmentFile)
  67.         flexsizer.Add(attachmentbutton,0,wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
  68.         self.attachmenteditbox = wx.TextCtrl(panel, style = wx.TE_CENTRE)
  69.         self.attachmenteditbox.Disable()
  70.         flexsizer.Add(self.attachmenteditbox,0,wx.EXPAND)
  71.  
  72.         subjectlabel = wx.StaticText(panel, -1, "Subject:")
  73.         flexsizer.Add(subjectlabel,0,wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL)
  74.         self.subject = wx.TextCtrl(panel)
  75.         flexsizer.Add(self.subject,0,wx.EXPAND)
  76.  
  77.         messagelabel = wx.StaticText(panel, -1, "E-mail Message:")
  78.         flexsizer.Add(messagelabel,0,wx.ALIGN_RIGHT)
  79.         self.emailmessage = wx.TextCtrl(panel, style = wx.TE_MULTILINE)
  80.         flexsizer.Add(self.emailmessage,1,wx.EXPAND)
  81.  
  82.         flexsizer.AddSpacer(wx.Size(1,1))
  83.  
  84.         self.gauge = wx.Gauge(panel)
  85.         self.gauge.SetRange(100)
  86.         self.gauge.SetValue(30)
  87.         sendbutton = wx.Button(panel, 1001, "Send E-mail")
  88.         sendbutton.Bind(wx.EVT_BUTTON, self.SendTheEmail)
  89.         hsizer = wx.BoxSizer(wx.HORIZONTAL)
  90.         hsizer.Add(self.gauge,1,wx.RIGHT,15)
  91.         hsizer.Add(sendbutton,0,wx.ALIGN_CENTER_VERTICAL)
  92.         flexsizer.Add(hsizer,0,wx.EXPAND)
  93.  
  94.         byteslabel1 = wx.StaticText(panel, -1, "Bytes to Send:")
  95.         self.bytestosend = wx.StaticText(panel, -1, "0")
  96.         flexsizer.Add(byteslabel1,0,wx.ALIGN_RIGHT)
  97.         flexsizer.Add(self.bytestosend,0,wx.EXPAND)
  98.  
  99.         byteslabel2 = wx.StaticText(panel, -1, "Bytes Sent:")
  100.         self.bytessent = wx.StaticText(panel, -1, "0")
  101.         flexsizer.Add(byteslabel2,0,wx.ALIGN_RIGHT)
  102.         flexsizer.Add(self.bytessent,0,wx.EXPAND)
  103.  
  104.  
  105.         vertsizer.Add(flexsizer,1, wx.EXPAND|wx.ALL,30)
  106.  
  107.         # place values into appropriate text fields
  108.         # (these values can be initialized at the top of this script)
  109.  
  110.         self.toemailaddress.SetValue(toemail)
  111.         self.fromemailaddress.SetValue(fromemail)
  112.         self.subject.SetValue(subject)
  113.         self.emailmessage.SetValue(emailmsg)
  114.  
  115.         if os.path.exists(os.path.abspath(attachment)):
  116.             self.attachmenteditbox.SetValue(\
  117.             os.path.split(os.path.abspath(attachment))[1])
  118.  
  119.         panel.SetSizer(vertsizer)
  120.  
  121.         self.bytestosend.SetLabel(str(self.GetMimeSize()))
  122.  
  123.  
  124.  
  125.     # select an attachment file for the e-mail
  126.     def SelectAttachmentFile(self, event):
  127.  
  128.         filedlgbox = wx.FileDialog(self,\
  129.             message="Select  an Attachment  File", \
  130.             defaultDir=os.getcwd(), \
  131.             defaultFile='', \
  132.             wildcard="Any File (*.*)|*.*", \
  133.             style=wx.OPEN | wx.CHANGE_DIR | wx.HIDE_READONLY)
  134.  
  135.         if filedlgbox.ShowModal() == wx.ID_OK:
  136.             global attachment
  137.             attachment = filedlgbox.GetFilenames()[0].strip()
  138.             self.attachmenteditbox.SetValue(os.path.split(attachment)[1])
  139.  
  140.         filedlgbox.Destroy()
  141.  
  142.         self.bytestosend.SetLabel(str(self.GetMimeSize()))
  143.  
  144.         event.Skip()
  145.  
  146.  
  147.  
  148.     def GetMimeSize(self):
  149.  
  150.         # get size of current e-mail mime object
  151.  
  152.         tempmime = MIMEMultipart()
  153.         tempmime['To'] = self.toemailaddress.GetValue().strip()
  154.         tempmime['From'] = self.fromemailaddress.GetValue().strip()
  155.         tempmime['Subject'] = self.subject.GetValue().strip()
  156.  
  157.         # add the e-mail message to the mime object
  158.         tempmime.attach(MIMEText(self.emailmessage.GetValue()))
  159.  
  160.         # add an attachment file to the mime object if selected
  161.         if attachment.strip() != '':
  162.             thisfile = os.path.abspath(attachment)
  163.             if os.path.exists(thisfile):
  164.                 attachmentmime = MIMEBase('application', "octet-stream")
  165.                 attachmentmime.set_payload( open(thisfile,"rb").read())
  166.                 Encoders.encode_base64(attachmentmime)
  167.                 attachmentmime.add_header('Content-Disposition',\
  168.                 'attachment; filename="%s"' % os.path.basename(thisfile))
  169.                 tempmime.attach(attachmentmime)
  170.  
  171.         mimesize = len(tempmime.as_string())
  172.  
  173.         tempmime = None
  174.  
  175.         return mimesize
  176.  
  177.  
  178.     # send the e-mail using python's smtplib module
  179.     def SendTheEmail(self, event):
  180.  
  181.         # how can I determine the number of bytes that have
  182.         # been forwarded whilst the e-mail is being sent ?
  183.         global bytes_sent
  184.         bytes_sent = 0
  185.  
  186.         # set gauge value to zero - max value = 100 (%)
  187.         self.gauge.SetValue(0)
  188.  
  189.         self.bytestosend.SetLabel(str(self.GetMimeSize()))
  190.         self.bytessent.SetLabel('0')
  191.  
  192.         # create a multi-part mime object for the
  193.         # e-mail message and file attachment
  194.  
  195.         thismime = MIMEMultipart()
  196.         thismime['To'] = self.toemailaddress.GetValue().strip()
  197.         thismime['From'] = self.fromemailaddress.GetValue().strip()
  198.         thismime['Subject'] = self.subject.GetValue().strip()
  199.  
  200.         # add the e-mail message to the mime object
  201.         thismime.attach(MIMEText(self.emailmessage.GetValue()))
  202.  
  203.         # add an attachment file to the mime object if selected
  204.         if attachment.strip() != '':
  205.             thisfile = os.path.abspath(attachment)
  206.             if os.path.exists(thisfile):
  207.                 attachmentmime = MIMEBase('application', "octet-stream")
  208.                 attachmentmime.set_payload( open(thisfile,"rb").read())
  209.                 Encoders.encode_base64(attachmentmime)
  210.                 attachmentmime.add_header('Content-Disposition',\
  211.                 'attachment; filename="%s"' % os.path.basename(thisfile))
  212.                 thismime.attach(attachmentmime)
  213.             else:
  214.                 dlg = wx.MessageDialog(self,\
  215.                 message='Attachment file ' + thisfile + ' is missing.',\
  216.                 caption='Attachment Missing',style=wx.OK|\
  217.                 wx.ICON_INFORMATION)
  218.                 dlg.ShowModal()
  219.                 dlg.Destroy()
  220.  
  221.         # send the e-mail
  222.         smtpobj = smtplib.SMTP(smtp_server)
  223.         smtpobj.sendmail(self.fromemailaddress.GetValue().strip(), \
  224.                             self.toemailaddress.GetValue().strip(), \
  225.                             thismime.as_string())
  226.  
  227.         smtpobj.close()
  228.  
  229.  
  230.         event.Skip()
  231.  
  232.  
  233.  
  234. if __name__ == '__main__':
  235.     app = wx.App()
  236.     theframe = MainFrame(None)
  237.     theframe.Show()
  238.     app.MainLoop()
  239.  
  240.  
  241.  
Dec 4 '06 #1
Share this Question
Share on Google+
1 Reply


bartonc
Expert 5K+
P: 6,596
I'm looking into socket byte counts. In the meantime, one line stuck out as I was reading your code:
Expand|Select|Wrap|Line Numbers
  1.         tempmime = None
  2.  
doesn't free up memory immediately. It does set the refcount to zero (if there are no other reference) by reseting the value of the temporary variable to None, so it will eventually be garbage collected. Your intention was probably to
Expand|Select|Wrap|Line Numbers
  1.         del tempmime
  2.  
which frees up memory immediately.
Dec 6 '06 #2

Post your reply

Sign in to post your reply or Sign up for a free account.