Exchangelib:按 conversation_id 过滤电子邮件
Exchangelib: Filtering email by conversation_id
我正在尝试使用 exchangelib 阅读带有某些 conversation_id 的电子邮件,并且只阅读 2 个属性:eid 和 datetime_received。
我不知道为什么下面的代码不起作用:
from exchangelib import Credentials, Account, Configuration, DELEGATE, EWSDateTime, EWSTimeZone, ExtendedProperty, Message
from exchangelib.properties import ConversationId
def read_latest_eid(conversation_id_, email_address_, password):
convert_ID_to_entryID = lambda x: ''.join('{:02x}'.format(i) for i in x).upper().strip()
class EntryID(ExtendedProperty):
property_tag = 4095
property_type = 'Binary'
try:
Message.register('eid', EntryID)
except:
Message.deregister('eid')
Message.register('eid', EntryID)
credentials = Credentials(email_address_, password)
config = Configuration(server='outlook.office365.com', credentials=credentials)
account = Account("xxx@abc.eu", config=config, access_type=DELEGATE,
autodiscover=False)
result = []
conversationid_to_search = ConversationId(conversation_id_)
print('*** Search following conversation id:', conversationid_to_search, type(conversationid_to_search))
print('*** id:', conversationid_to_search.id, type(conversationid_to_search.id))
for i in account.inbox.filter(conversation_id=conversationid_to_search).only("datetime_received", "eid"):
print('*** i:', i, type(i))
result.append(list((i.datetime_received.astimezone().strftime("%d/%m/%Y, %H:%M:%S"),
convert_ID_to_entryID(i.eid))))
Message.deregister('eid')
return result
# For testing read_latest_id
if __name__ == "__main__":
conversation_id = '7FD7341602EE405193F1F996D7DD8D6A'
print(read_latest_eid(conversation_id))
当前错误是:
*** Search following conversation id: ConversationId(id='7FD7341602EE405193F1F996D7DD8D6A') <class 'exchangelib.properties.ConversationId'>
*** id: 7FD7341602EE405193F1F996D7DD8D6A <class 'str'>
*** i: Id is malformed. <class 'exchangelib.errors.ErrorInvalidIdMalformed'>
Traceback (most recent call last):
File "h:\Codes\Subscribe_Email\Read_Open_Mail.py", line 171, in <module>
print(read_latest_eid(conversation_id))
File "h:\Codes\Subscribe_Email\Read_Open_Mail.py", line 149, in read_latest_eid
result.append(list((i.datetime_received.astimezone().strftime("%d/%m/%Y, %H:%M:%S"),
AttributeError: 'ErrorInvalidIdMalformed' object has no attribute 'datetime_received'
任何解决方法的指针将不胜感激。
更新:
我从本地 运行 outlook 程序中得到了 conversation_id。
以下代码从我的 outlook 中输出当前选择的电子邮件。
请参阅下面的“return”行。
def read_selected_email(outlook):
# This function reads the properties of selected Outlook-Email.
try:
messages = outlook.ActiveExplorer().Selection
message = messages(1)
# print('Sender:', message.Sender)
# print('Date:', message.ReceivedTime)
# print('Titel:', message.subject)
# print('Sender:', message.Sender)
# print('Recipient:', message.To)
# print('ConversationID', message.ConversationID)
# received_time = str(datetime.strptime(str(message.ReceivedTime).rstrip(
# "+00:00"), '%Y-%m-%d %H:%M:%S').date())
received_time = str(message.ReceivedTime).rstrip("+00:00")
print(received_time)
try:
received_time = datetime.strptime(received_time, '%Y-%m-%d %H:%M:%S')
# print('+1')
except:
try:
received_time = datetime.strptime(received_time, '%Y-%m-%d %H:%M')
# print('+2')
except:
received_time = datetime.strptime(received_time, '%Y-%m-%d %H:%M:%S.%f')
received_time = str(received_time.date())
# print('***', message)
return [{'Datum': received_time, 'Titel': message.subject,
'Sender': message.SenderName.split("(")[0], 'Recipient':
message.To, 'Kommentar': '',
'ConversationID': message.ConversationID}]
except AttributeError:
print('*** No Email selected')
pass
except Exception as e:
print(e)
pass
# For testing read_selected_email
if __name__ == "__main__":
outlook = win32com.client.Dispatch("Outlook.Application")
outlook_mapi = outlook.GetNamespace("MAPI")
print(read_selected_email(outlook))
其实我只是想重现https://github.com/ecederstrand/exchangelib/issues/261中的解决方案
通过根据 conversation_id 过滤搜索
我不确定,为什么它对我不起作用。
您的交换服务器不喜欢您对话 ID 的格式。您从服务器收到 ErrorInvalidIdMalformed 错误。
您是直接从服务器获取对话 ID 吗?如果没有,您可以使用 ConvertID 服务将 ID 转换为正确的格式,该服务可通过 account.protocol.convert_ids()
方法获得。
如果您不知道对话 ID 的原始格式,您可以尝试所有格式:
from exchangelib.properties import ID_FORMATS, EWS_ID, AlternateId
i = '7FD7341602EE405193F1F996D7DD8D6A'
for fmt in ID_FORMATS:
res = list(account.protocol.convert_ids([
AlternateId(
id=i, format=fmt,
mailbox=account.primary_smtp_address)
], destination_format=EWS_ID))[0]
if isinstance(res, Exception):
print(f'Error converting from {fmt} to {EWS_ID}: {res}')
else:
print(f'Sucessfully converted from {fmt} to {EWS_ID}: {res}')
您也可能需要使用 MAPI 属性 搜索 ConversationID 字段。应该这样做(基于 https://social.msdn.microsoft.com/Forums/office/en-US/5551df43-d833-4352-b27a-70e18ef71576/how-can-i-compare-conversation-id-from-exchange-web-services-with-outlook-conversation-id-?forum=outlookdev and https://github.com/ecederstrand/exchangelib/issues/146):
class MAPIConverstationID(ExtendedProperty):
property_tag = 0x3013
property_type = 'Binary'
Message.register('mapi_cid', MAPIConverstationID)
for m in account.filter(mapi_cid=my_win32com_cid):
print(m.mapi_cid)
我正在尝试使用 exchangelib 阅读带有某些 conversation_id 的电子邮件,并且只阅读 2 个属性:eid 和 datetime_received。 我不知道为什么下面的代码不起作用:
from exchangelib import Credentials, Account, Configuration, DELEGATE, EWSDateTime, EWSTimeZone, ExtendedProperty, Message
from exchangelib.properties import ConversationId
def read_latest_eid(conversation_id_, email_address_, password):
convert_ID_to_entryID = lambda x: ''.join('{:02x}'.format(i) for i in x).upper().strip()
class EntryID(ExtendedProperty):
property_tag = 4095
property_type = 'Binary'
try:
Message.register('eid', EntryID)
except:
Message.deregister('eid')
Message.register('eid', EntryID)
credentials = Credentials(email_address_, password)
config = Configuration(server='outlook.office365.com', credentials=credentials)
account = Account("xxx@abc.eu", config=config, access_type=DELEGATE,
autodiscover=False)
result = []
conversationid_to_search = ConversationId(conversation_id_)
print('*** Search following conversation id:', conversationid_to_search, type(conversationid_to_search))
print('*** id:', conversationid_to_search.id, type(conversationid_to_search.id))
for i in account.inbox.filter(conversation_id=conversationid_to_search).only("datetime_received", "eid"):
print('*** i:', i, type(i))
result.append(list((i.datetime_received.astimezone().strftime("%d/%m/%Y, %H:%M:%S"),
convert_ID_to_entryID(i.eid))))
Message.deregister('eid')
return result
# For testing read_latest_id
if __name__ == "__main__":
conversation_id = '7FD7341602EE405193F1F996D7DD8D6A'
print(read_latest_eid(conversation_id))
当前错误是:
*** Search following conversation id: ConversationId(id='7FD7341602EE405193F1F996D7DD8D6A') <class 'exchangelib.properties.ConversationId'>
*** id: 7FD7341602EE405193F1F996D7DD8D6A <class 'str'>
*** i: Id is malformed. <class 'exchangelib.errors.ErrorInvalidIdMalformed'>
Traceback (most recent call last):
File "h:\Codes\Subscribe_Email\Read_Open_Mail.py", line 171, in <module>
print(read_latest_eid(conversation_id))
File "h:\Codes\Subscribe_Email\Read_Open_Mail.py", line 149, in read_latest_eid
result.append(list((i.datetime_received.astimezone().strftime("%d/%m/%Y, %H:%M:%S"),
AttributeError: 'ErrorInvalidIdMalformed' object has no attribute 'datetime_received'
任何解决方法的指针将不胜感激。
更新: 我从本地 运行 outlook 程序中得到了 conversation_id。 以下代码从我的 outlook 中输出当前选择的电子邮件。 请参阅下面的“return”行。
def read_selected_email(outlook):
# This function reads the properties of selected Outlook-Email.
try:
messages = outlook.ActiveExplorer().Selection
message = messages(1)
# print('Sender:', message.Sender)
# print('Date:', message.ReceivedTime)
# print('Titel:', message.subject)
# print('Sender:', message.Sender)
# print('Recipient:', message.To)
# print('ConversationID', message.ConversationID)
# received_time = str(datetime.strptime(str(message.ReceivedTime).rstrip(
# "+00:00"), '%Y-%m-%d %H:%M:%S').date())
received_time = str(message.ReceivedTime).rstrip("+00:00")
print(received_time)
try:
received_time = datetime.strptime(received_time, '%Y-%m-%d %H:%M:%S')
# print('+1')
except:
try:
received_time = datetime.strptime(received_time, '%Y-%m-%d %H:%M')
# print('+2')
except:
received_time = datetime.strptime(received_time, '%Y-%m-%d %H:%M:%S.%f')
received_time = str(received_time.date())
# print('***', message)
return [{'Datum': received_time, 'Titel': message.subject,
'Sender': message.SenderName.split("(")[0], 'Recipient':
message.To, 'Kommentar': '',
'ConversationID': message.ConversationID}]
except AttributeError:
print('*** No Email selected')
pass
except Exception as e:
print(e)
pass
# For testing read_selected_email
if __name__ == "__main__":
outlook = win32com.client.Dispatch("Outlook.Application")
outlook_mapi = outlook.GetNamespace("MAPI")
print(read_selected_email(outlook))
其实我只是想重现https://github.com/ecederstrand/exchangelib/issues/261中的解决方案 通过根据 conversation_id 过滤搜索 我不确定,为什么它对我不起作用。
您的交换服务器不喜欢您对话 ID 的格式。您从服务器收到 ErrorInvalidIdMalformed 错误。
您是直接从服务器获取对话 ID 吗?如果没有,您可以使用 ConvertID 服务将 ID 转换为正确的格式,该服务可通过 account.protocol.convert_ids()
方法获得。
如果您不知道对话 ID 的原始格式,您可以尝试所有格式:
from exchangelib.properties import ID_FORMATS, EWS_ID, AlternateId
i = '7FD7341602EE405193F1F996D7DD8D6A'
for fmt in ID_FORMATS:
res = list(account.protocol.convert_ids([
AlternateId(
id=i, format=fmt,
mailbox=account.primary_smtp_address)
], destination_format=EWS_ID))[0]
if isinstance(res, Exception):
print(f'Error converting from {fmt} to {EWS_ID}: {res}')
else:
print(f'Sucessfully converted from {fmt} to {EWS_ID}: {res}')
您也可能需要使用 MAPI 属性 搜索 ConversationID 字段。应该这样做(基于 https://social.msdn.microsoft.com/Forums/office/en-US/5551df43-d833-4352-b27a-70e18ef71576/how-can-i-compare-conversation-id-from-exchange-web-services-with-outlook-conversation-id-?forum=outlookdev and https://github.com/ecederstrand/exchangelib/issues/146):
class MAPIConverstationID(ExtendedProperty):
property_tag = 0x3013
property_type = 'Binary'
Message.register('mapi_cid', MAPIConverstationID)
for m in account.filter(mapi_cid=my_win32com_cid):
print(m.mapi_cid)