Leyalic
Leyalic

Reputation: 3

Using Python and win32 how can I open multiple emails simultaneously without sending?

I need to send a lot of emails to many different recipients with many attachments. I'd like to be able to review the emails and add any additional attachments that may need to be added prior to sending. Currently this code will only open one window (email), requiring that one to be sent or closed before showing another. How can I get all of the emails open and visible at the same time?

def mailer(text, subject, recipient, attachments):
    import win32com.client as win32

    list(attachments)
    outlook = win32.Dispatch('outlook.application')
    mail = outlook.CreateItem(0)
    mail.To = recipient
    mail.Subject = subject
    mail.HtmlBody = text
    for each in attachments:
        mail.Attachments.Add(Source=each)
    mail.Display(True)

mailer("", " TEST 1", test_address, "")
mailer("", " TEST 2", test_address, "")
mailer("", " TEST 3", test_address, "")
mailer("", " TEST 4", test_address, "")

Upvotes: 0

Views: 1412

Answers (2)

Dmitry Streblechenko
Dmitry Streblechenko

Reputation: 66276

Call mail.display(false) - that will display the window modelessly.

Upvotes: 3

Nahkki
Nahkki

Reputation: 872

In general, statements in python are run sequentially.

If you have a script like:

print "a"
print "b"
print "c"
print "d"

then your expected output would be:

$ play.py
a
b
c
d

This is what is happening as you run:

mailer("", " TEST 1", test_address, "")
mailer("", " TEST 2", test_address, "")
mailer("", " TEST 3", test_address, "")
mailer("", " TEST 4", test_address, "")

Python is running these statements in the order in which you give them. So mailer("", " TEST 2", test_address, "") will only be run once mailer("", " TEST 1", test_address, "") has completed and so on, in order, until the last statement has been run.

How can you fix this?

My first instinct would be to check out python's multiprocessing package: http://docs.python.org/library/multiprocessing.html

You could change your code to something like:

from multiprocessing import Process

def mailer(text, subject, recipient, attachments):
    import win32com.client as win32

    list(attachments)
    outlook = win32.Dispatch('outlook.application')
    mail = outlook.CreateItem(0)
    mail.To = recipient
    mail.Subject = subject
    mail.HtmlBody = text
    for each in attachments:
        mail.Attachments.Add(Source=each)
    mail.Display(True)

if __name__ == '__main__':
    Process(mailer("", " TEST 1", test_address, ""))
    Process(mailer("", " TEST 2", test_address, "")
    Process(mailer("", " TEST 3", test_address, "")
    Process(mailer("", " TEST 4", test_address, "")

Whether this or another package(like threading here: https://docs.python.org/2/library/threading.html) or even a third party library would be best really depends on the number of message you would like to have open at once and the CPU/RAM requirements of each.

Upvotes: 0

Related Questions