I try to list all the recipients I send emails to by using MAPI.
On MSDN, I found a script which can complete this task. One question is, the mail group only shows the group address. But I want to list all the individual addresses within the group.
Anyone know if this is possible?
recips = message.Recipients
for recip in recips:
pa = recip.PropertyAccessor
smtpAddress = pa.GetProperty(PR_SMTP_ADDRESS)
Process the Recipient.AddressEntry.Members collection recursively. It will be null for the recipients who are not distribution lists.
Related
I am working on a CRM, where I am receiving hundreds of emails for offers/requirements per day. I am building an API that will process the email and will insert entries in the CRM.
I am using imap_tools to get the mails in my API. but I am stuck at the point when there's a thread/conversation. I read some articles regarding using reference or in-reply-to header from the mail. but unlucky so far. I have also tried using the message-id but it gave me the same email thread instead of multiple emails.
I am getting an email thread/conversation as a single email and I want to get separated emails so I can process them easily.
here's what I have done so far.
from imap_tools import MailBox
with MailBox('mail.mail.com').login('abc#abc.com', 'password', 'INBOX') as mailbox:
for msg in mailbox.fetch():
From = msg.headers['from'][0]
To = msg.headers['to'][0]
subject = msg.headers['subject'][0]
received_date = msg.headers['date'][0]
raw_email = msg.text
process_email(raw_email) #processing the email
The issue you are facing is not related to the headers reference or in-reply-to. Most email clients will append the previous email as quoted text to the new mail when you reply. Hence in a thread, a mail will have the body of all previous mails as quoted text.
In most cases, and I say most since the Email standards vary a lot from client to client, the client will quote the previous mail by pretending > before all quoted lines
new message
> old message
>> very old message
As a hacky solution, you can drop all lines that start with >
In python, you can splitlines() and filter
lines = email.splitlines()
new_lines = [i for i in lines if not i.startswith('>')]
or
new_lines = list(filter(lambda i: not i.startswith('>'), lines))
you may use regular expressions or other techniques too.
the issue with the solution is obvious, if an email contains > else where it will cause loss of information. Hence a more complicated approach is to select lines with > and compare them with the previous emails in the thread using references and remove those which match.
Google has their patented implementation here
https://patents.google.com/patent/US7222299
Source: How to remove the quoted text from an email and only show the new text
Edit
I realized Gmail follows the > quoting and other clients may follow other methods. There's a Wikipedia article on it: https://en.wikipedia.org/wiki/Posting_style
conceptually the approach needed will be similar, but different types of clients will need to be handled
I used win32.client and could successfully access members of an exchange distribution list using python. However, because there are two users with the same first and last name, I would like to be able to access their email address instead of the name.
Using below loop, I can go through the members of Exchange Distribution List and print the name of all members:
import win32com.client
outlook_obj = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
#This function gets outlook object and retuens all the members of ALL Groups
address_lists = outlook_obj.AddressLists
#Access Exchange Distribution Lists
dist_lists = address_lists['All Distribution Lists']
return(dist_lists)
dl_index = a_numerical_index_greater_than_zero # you can try different numbers until you find the index of your desired distributionList, or loop thorough all the members and find what you are looking for
for m in dist_lists.AddressEntries.Item(dl_index).GetExchangeDistributionList().Members:
print(str(m))
The above script perfectly works and prints out all the name of all the members of the distribution list. However, I am looking for distinct email address of the members, as I see names are not distinct (I can have two people with the same name Jack Smith, but jack.smith#xyz.com and jack.smith2#xyz.com are still distinct).
I used the object definition from this source to build above code, but it seems I am unable to connect members to their email address.
Appreciate any help!
Okay - I got my answer and I am sharing in case others may need this.
Indeed below script is returning the addressEntry of the Member
dist_lists.AddressEntries.Item(dl_index).GetExchangeDistributionList().Members[0].GetExchangeUser()
and addressEntry can give you access to all details of the account, including email address. Below is the exact code to fetch email address of the user
dist_lists.AddressEntries.Item(dl_index).GetExchangeDistributionList().Members[0].GetExchangeUser().PrimarySmtpAddress
I am trying to grab a list of messages that have a specific content e.g. billing emails and work on data in there.
In order to get these messages, I run the following
service.users().messages().list(userId=user_id, page_token=page_token, q=query).execute()
which returns all the messages.
I want to limit the messages that I get to confirm to the following criteria:
Sent in the last two days
Definitely deny if from: address not in a list of email addresses i.e. blacklist e.g. notifications, facebook
Definitely accept if from: address in a list of email addresses i.e. whitelist
Look if the subject: matches a set of strings
I understand that I can create a query that would match the email address and subject (from:bill#pge.com AND subject:"Your bill for this month"), but the blacklist and whitelist, as mentioned above, can become significantly large as the scope and the number of vendors I can accept increases, and similar is the case with subject. So my question is:
Is there a limit on the number of query terms?
Is there a way to achieve this other than generating a very long query string combining the black list whitelist and subject (from:abc#this.com AND NOT from:xyz#that.com AND subject:"Your bill" AND subject:"This month's bill")?
Note: For project settings I mostly conform to https://developers.google.com/gmail/api/quickstart/python
There's no limit documented for the number of query terms you can use. Yes, you would have to create programmatically a long query string combining all the emails from the lists. Here [1] you can check the operators you can use, the best approach would be like this:
1) Use "after" or "newer" operators with a timestamp from 2 days before the current date.
2) -from:{xxx#xxx.com xxx#xxx.com ...}
3) from:{xxx#xxx.com xxx#xxx.com ...}
4) subject:{xxx xxx ...}
[1] https://support.google.com/mail/answer/7190
=)
I need get all messages from email inbox with specific address.
For that i use command:
self.server.search(None, '(HEADER FROM "test#gmail.com")')
and it's work but when I try find message form st#gmail.com I got the same results. And I know with this criteria I searching all messages CONTAINS specific string. But for me test#gmail.com and st#gmail.com is diffrents addresses. How can I search for EQUAL not CONTAINS addresses?
import imaplib
self.server = imaplib.IMAP4(self.imap_ssl_host, self.imap_ssl_port)
You can try searching for <test#gmail.com> instead of test#gmail.com.
A message from test#gmail.com usually says From: Firstname Lastname <test#gmail.com>, which contains the substring <test#, and most IMAP searches are substring searches, including FROM. If this hack is enough for you and whatever server you're using, good for you, otherwise you need to do clientside filtering to remove the false positives.
I am facing a following problem, I want to have an allowed senders list in my email parser so it will look like:
allowed_emails = ["email1#gmail.com", "email2#gmail.com", "email3#gmail.com"]
I want to use this list in this line, for now it works only with one allowed_sender, how to send a list as an argument?
result, data = mail.search(None,'(UNSEEN FROM "%s")' % allowed_sender)