Define mailbox to which to save an email - win32client python - python

I would like to save an email to the drafts folder of a shared mailbox using the win32 API for Outlook. I can save an email to my (default?) mailbox drafts folder using the below:
def TestEmailer(text, subject, recipient):
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.To = recipient
mail.Subject = subject
mail.HtmlBody = text
mail.Save()
TestEmailer('hello world', 'test', 'recipient#gmail.com')
Thanks to this previous question I can see that the SendUsingAccount() method can be used to send from a defined mailbox. Is there an equivalent method for saving to the drafts folder of a defined mailbox?

You can select Save () when you switch your account to send email, which will be saved in the draft box of the new account.
Code:
import win32com.client as win32
def send_mail():
outlook_app = win32.Dispatch('Outlook.Application')
# choose sender account
send_account = None
for account in outlook_app.Session.Accounts:
if account.DisplayName == 'sender#hotmail.com':
send_account = account
break
mail_item = outlook_app.CreateItem(0) # 0: olMailItem
# mail_item.SendUsingAccount = send_account not working
# the following statement performs the function instead
mail_item._oleobj_.Invoke(*(64209, 0, 8, 0, send_account))
mail_item.Recipients.Add('receipient#outlook.com')
mail_item.Subject = 'Test sending using particular account'
mail_item.BodyFormat = 2 # 2: Html format
mail_item.HTMLBody = '''
<H2>Hello, This is a test mail.</H2>
Hello Guys.
'''
mail_item.Save()
if __name__ == '__main__':
send_mail()
Here's a bit of black magic here. Setting mail_item.SendUsingAccount directly won't work. The return value is none. Always send mail from the first email account. You need to call the method of oleobj_.Invoke().
Updated:
Oleobj document: https://github.com/decalage2/oletools/wiki/oleobj
Similar case: python win32com outlook 2013 SendUsingAccount return exception

Related

Opening outlook with filled fields using Python

I am trying to create a function to open a new Outlook message, but I would like the message to appear already with the recipient, subject fields.
So far what I have found is how to open a new Outlook window with the recipient, but I still can't get the subject to be displayed.
import webbrowser
webbrowser.open('mailto:email#domain.com', new=1)
Hope u can help me, ty.
mailto would work fine as long as you don't want HTML body or attachments. You can specify to/cc/bbc, subject, and body.
Something along the lines:
mailto:user1#domain.demo?subject=Test%20Subject&body=Test%20body&cc=user2#domain.demo&bcc=user3#domain.demo
And it will work under any OS and any email client.
Here is a potential solution using win32.com.client:
import win32.com.client as win32
outlook = win32.Dispatch("Outlook.Application") # Starts Outlook application
new_email = outlook.CreateItem(0) # Creates new email item
new_email.To = "email#domain.com" # Add recipients separated by comma or semicolon
new_email.Subject = "How to create new Outlook email in Python" # Your email subject
new_email.Body = "This text will be the body of your new email" # Your email body
new_email.Display(True) # Displays the new email item

how to use win32com.mapi get new email from outlook in python?

I wanna get a message when a new email into outlook.
I try to use python.
I can find that folders,but can't find the way to get the number of new email.
import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
accounts = win32com.client.Dispatch("Outlook.Application").Session.Accounts;
inbox = outlook.Folders(accounts[0].DeliveryStore.DisplayName)
for obj in inbox.Folders: #how to know how many new email in this dir?
try:
if hasattr(obj, "__str__"):
dirName = obj.__str__() #as some new email in this obj.
for message in obj.items: # how to know this email is not be read ?
subject = sender = ''
if hasattr(message, "Subject"):
subject = message.Subject
if hasattr(message, "SenderName"):
sender = message.SenderName
print(sender, subject)
except Exception as e:
print(f"i:{obj.__str__()}")
and where can I learn win32com.mapi?
I wanna know what func can I use in mapi.
give me some info,please~
so much thanks!
Are you looking for unread messages? Use MAPIFolder.Items.Restrict("[Unread] = true") to retrieve Items collection with the restriction applied.

Python automated Outlook email: change sender or default reply-to address

I'm using code similar to Steve Townsend's answer from this question: Send Outlook Email Via Python?
to send an email by running a python script. How can I edit the default reply-to address, so that when someone replies to the automated email it will get sent to a specific address? Alternatively, can I modify the address that the email is sent from? I tried to modify the Msg.SentOnBehalfOfName property but had no success with that. Note that the address is an alias so I can't log into the account in Outlook.
import win32com.client
def send_mail_via_com(text, subject, recipient, profilename="Outlook2003"):
s = win32com.client.Dispatch("Mapi.Session")
o = win32com.client.Dispatch("Outlook.Application")
s.Logon(profilename)
Msg = o.CreateItem(0)
Msg.To = recipient
Msg.CC = "moreaddresses here"
Msg.BCC = "address"
Msg.Subject = subject
Msg.Body = text
attachment1 = "Path to attachment no. 1"
attachment2 = "Path to attachment no. 2"
Msg.Attachments.Add(attachment1)
Msg.Attachments.Add(attachment2)
Msg.Send()
You can try the following code to choose sender address and recipient address freely.
import win32com.client as win32
def send_mail():
outlook_app = win32.Dispatch('Outlook.Application')
# choose sender account
send_account = None
for account in outlook_app.Session.Accounts:
if account.DisplayName == 'sender#hotmail.com':
send_account = account
break
mail_item = outlook_app.CreateItem(0) # 0: olMailItem
# mail_item.SendUsingAccount = send_account not working
# the following statement performs the function instead
mail_item._oleobj_.Invoke(*(64209, 0, 8, 0, send_account))
mail_item.Recipients.Add('receipient#outlook.com')
mail_item.Subject = 'Test sending using particular account'
mail_item.BodyFormat = 2 # 2: Html format
mail_item.HTMLBody = '''
<H2>Hello, This is a test mail.</H2>
Hello Guys.
'''
mail_item.Send()
if __name__ == '__main__':
send_mail()
If you are interesting, you can refer this case.

Extract sender's email address from Outlook Exchange in Python using win32

I am trying to extract the sender's email address from outlook 2013 using win32 package in python. There are two kinds of email address type in my Inbox, exchange and smtp. If I try to print the the sender's email address of Exchange type, I am getting this:
/O=EXCHANGELABS/OU=EXCHANGE ADMINISTRATIVE GROUP(FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=6F467C825619482293F429C0BDE6F1DB-
I have already gone through this link but couldn't find a function through which I can extract the smtp address.
Below is my code:
from win32com.client import Dispatch
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
folders = inbox.Folders
for msg in all_inbox:
print msg.SenderEmailAddress
Currently all the Email Address are coming like this:
/O=EXCHANGELABS/OU=EXCHANGE ADMINISTRATIVE GROUP(FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=6F467C825619482293F429C0BDE6F1DB-
I found a solution to this in VB.net link but don't know how to rewrite the same thing in Python.
Firstly, your code will fail if you have an item other than MailItem in the folder, such as ReportItem, MeetingItem, etc. You need to check that the Class property is 43 (olMail).
Secondly, you need to check the sender email address type and use the SenderEmailAddress property only for the "SMTP" address type. In VB:
for each msg in all_inbox
if msg.Class = 43 Then
if msg.SenderEmailType = "EX" Then
print msg.Sender.GetExchangeUser().PrimarySmtpAddress
Else
print msg.SenderEmailAddress
End If
End If
next
I am just modifying the program given above in Python.
from win32com.client import Dispatch
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
folders = inbox.Folders
for msg in all_inbox:
if msg.Class==43:
if msg.SenderEmailType=='EX':
print msg.Sender.GetExchangeUser().PrimarySmtpAddress
else:
print msg.SenderEmailAddress
This will print out all the sender's email address in your inbox folders only.
I had this same problem workin with win32com today. I found the solution here.
Using your example it would be:
from win32com.client import Dispatch
outlook = Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder("6")
all_inbox = inbox.Items
folders = inbox.Folders
for msg in all_inbox:
if msg.Class==43:
if msg.SenderEmailType=='EX':
if msg.Sender.GetExchangeUser() != None:
print msg.Sender.GetExchangeUser().PrimarySmtpAddress
else:
print msg.Sender.GetExchangeDistributionList().PrimarySmtpAddress
else:
print msg.SenderEmailAddress
This should solve the group mail issue.

Python - Sending Outlook email from different address using pywin32

I have a working script that creates and sends Outlook emails successfully through pywin32, but I would like to send the email from a different, generic account. I have access to this generic account (and password) and even have the mailbox opened concurrently in Outlook, if that helps.
Trying something like msg.From = "generic#email.com" returns AttributeError: Property 'CreateItem.From' can not be set..
Is there any way to accomplish this without using SMTP? Even just changing the headers to reflect the generic account as the From and Reply-To address would work.
Edit: Using Win7 32bit, Outlook 2010, python 2.7, and the pywin32 module to create the following bit of code:
from win32com.client import Dispatch
mailer = Dispatch("Outlook.Application")
msg = mailer.CreateItem(0)
msg.To = emailTo
msg.CC = emailCC
msg.Subject = emailSubject
msg.Body = emailBody
msg.Send()
This part works perfectly fine, but it sends the emails through the user that's logged in, myself. I'd rather send it from a generic account so that it looks more official and replies are received there instead of in my mailbox.
I know this comes late, but this is another way I've managed to make this work. With this I was able to send e-mails with my non-default e-mail address in outlook:
import win32com.client as win32
outlook = win32.Dispatch('outlook.application')
mail = outlook.CreateItem(0)
mail.Subject = "Test subject"
mail.To = "yourrecipient#gmail.com"
# If you want to set which address the e-mail is sent from.
# The e-mail needs to be part of your outlook account.
From = None
for myEmailAddress in outlook.Session.Accounts:
if "#gmail.com" in str(myEmailAddress):
From = myEmailAddress
break
if From != None:
# This line basically calls the "mail.SendUsingAccount = xyz#email.com" outlook VBA command
mail._oleobj_.Invoke(*(64209, 0, 8, 0, From))
mail.Send()
You can send mails via exchange using the extended mapi. It takes a little more effort than what you tried so far but it is very powerful, e.g. it allows to select an outlook profile to be used.
Have a look at site-packages\win32comext\mapi\demos\mapisend.py of your pywin32 installation.
EDIT:
As said in the comment, try the following to be sure Outlook is using the profile you want. Look for this line:
session = mapi.MAPILogonEx(0, MAPIProfile, None, mapi.MAPI_EXTENDED |
mapi.MAPI_USE_DEFAULT)
and change it to
session = mapi.MAPILogonEx(0, MAPIProfile, None, mapi.MAPI_EXTENDED |
mapi.MAPI_LOGON_UI)
Call SendEMAPIMail like this:
SendEMAPIMail(SendSubject, SendMessage, SendTo, MAPIProfile=None)
A dialog should appear offering to select the Outlook profile.
EDIT:
As #caseodilla found out, if Outlook is running with another profile, MAPILogonEx seems to reuse the running session and its profile. In order to force mapi to use another profile add the MAPI_NEW_SESSION flag:
session = mapi.MAPILogonEx(0, MAPIProfile, None, mapi.MAPI_EXTENDED |
mapi.MAPI_LOGON_UI | mapi.MAPI_NEW_SESSION)

Categories