会議への招待がある場合、Python を使用して Outlook から電子メールを読み取ることができない

okwaves2024-01-25  8

ウェブ上のリソースから学習と実験を行って、いくつかのコードを作成することができました。

Outlook メールボックスに会議への招待が毎回表示されるという状況で行き詰まっています。コードの実行に失敗します。

Python で例外を処理する方法に関するガイダンスを探しています。

import csv  
import win32com.client

from datetime import datetime

outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items

# Create empty list to store results
data_set = list()
date_id = (datetime.today()).strftime('%Y%m%d') # Used to create the filename

#Iterating through email items in outlook folder  

for message in messages:
    if messages is not None:
         if len(inbox.Items) > 0:
                row = list()
                row.append(message.Subject)
                row.append(message.Categories)
                row.append(message.Sender)
                #row.append(message.Sender.Address)
                row.append(message.To)
                row.append(message.SentOn)
                row.append(message.CC)
                row.append(message.BCC)
                 
                # Stores the data in a list
                data_set.append(row)
                    
                
# Print out the result to a csv with headers
with open(date_id + "_"+ 'outlook_Data.csv', 'w', newline='', encoding='utf-8') as csv_file:
    headers = ['Subject', 'Category', 'From', 'To', 'Sent On', 'CC', 'BCC']
    wr = csv.writer(csv_file, delimiter=',')
    wr.writerow(headers)
    for line in data_set:
        wr.writerow(line)

「実行に失敗しました」とはどういう意味ですか?例外が発生しますか?

– スネークチャームブ

2020 年 9 月 3 日 10:45

行 (message.Sender) を指す属性エラーがスローされます。 raise AttributeError("%s.%s" % (self._username_, attr)) AttributeError: <unknown>.Sender

– SaaSy モンスター

2020 年 9 月 3 日 10:47

さらなる調査によると、電子メールは別のクラスとみなされ、会議には別のクラスが招待されます。会議への招待がない限りメールボックスではプログラムはスムーズに実行されます。

– SaaSy モンスター

2020 年 9 月 3 日 10:49

isinstance(message, TheMeetingInviteClass): continue の場合は?

– スネークチャームブ

2020 年 9 月 3 日 10:50

はい、メッセージ内の for メッセージの先頭に if isinstance(message, TheMeetingInviteClass): continue を適用しようとしましたが、機能しません。応募してるのかなコード行が間違っていますか?

– SaaSy モンスター

2020 年 9 月 3 日 10:52



------------------------

この問題はフィルタリングの問題に帰着します。さまざまなタイプのオブジェクトのリストがあり、その一部は処理してはなりません。

この回答では、受信トレイ内の電子メール オブジェクトのタイプをメッセージとし、会議出席依頼のタイプを MeetingInvitation とします。

これら 4 つのアプローチはいずれも適用できます。

試す/除外する/続行する

for message in messages:
    row = list()
    try:
        row.append(message.Subject)
        row.append(message.Categories)
        row.append(message.Sender)
        ...                 
        # Stores the data in a list
        data_set.append(row)
    except AttributeError as ex:
        print('Error', ex, 'skipping message', message)
        continue

ループの先頭でオブジェクトのタイプを確認します

 for message in messages:
     if isinstance(message, MeetingInvitation):
         continue
     row = list()

フィルタ組み込み関数を使用する

 filtered_messages = filter(lambda msg: not isinstance(msg, MeetingInvitation), messages)
 for message in filtered_messages:
     row = list()
     ...

リスト内包表記を使用します (リスト内包表記が多数ある場合)皆さん、ジェネレーターの理解の方が効率的です - [] を ()) に置き換えてください。

 filtered_messages = [msg for msg in msgs if not isinstance(msg, MeetingInvitation)] 
 for message in filtered_messages:
     row = list()
     ...

isinstance チェックを逆にして、メッセージではないものを除外することもできます。

if not isinstance(message, Message):
   continue

または、他の問題のあるタイプを除外するために拡張されます

if isinstance(message, (MeetingInvitation, SomethingElse)):
    continue

4 つのアプローチはすべて機能的に同等です。私の意見では、フィルタとリストの理解によるアプローチは、実際のメッセージ処理からフィルタリング プロセスを分離するため、よりクリーンです。

1

try/excel/ continue メソッドを試してみましたが、うまくいきました。無法に。完璧な解決策です。私はまだ Python を学習中なので、「AttributeError」が発生しました。作品を扱うのは私にとって非常に新しいことです。他の 2 つの方法は機能しませんでした。私は「isinstance」についていくつかの研究を行っています。このメソッドは今のところ正しく適用されていないと思います。

– SaaSy モンスター

2020 年 9 月 4 日 8:33



------------------------

Outlook カレンダー項目をスキップしたい場合のもう 1 つの解決策は、item.MessageClass を使用することです。以下は、サンプル コードと詳細の参照リンクです。

https://learn.microsoft.com/en-us/office/vba/outlook/Concepts/Forms/item-types-and-message-classes

import win32com.client
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")

inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items
messages.Sort("[ReceivedTime]", True)

for i, msg in enumerate(messages):
    print(msg.MessageClass) # use this in condition

    if msg.MessageClass=='IPM.Note':
        print('Its a Meeting')

        # Identify outlook exchange user
        if msg.SenderEmailType == "EX":
            print(msg.Sender.GetExchangeUser().PrimarySmtpAddress)
            msg_sender = msg.Sender.GetExchangeUser().PrimarySmtpAddress
        else:
            print(msg.SenderEmailAddress)
            msg_sender = msg.SenderEmailAddress
    elif msg.MessageClass =='IPM.Schedule.Meeting.Request':
        print('Its a Meeting')
    # Check only first 20 items change the number as required
    if i > 20:
        break
Some Outputs from above code
IPM.Note
IPM.Note
IPM.Schedule.Meeting.Request
Its a Meeting
IPM.Note
IPM.Schedule.Meeting.Request
Its a Meeting



------------------------

この課題を解決してくれた @snakecharmerb に感謝します。他の人が同様のコードに取り組む必要があるかもしれないので、完全に機能するコードを以下に示します。

import csv  
import win32com.client
from datetime import datetime

outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
inbox = outlook.GetDefaultFolder(6)
messages = inbox.Items


# Create empty list to store results
data_set = list()
date_id = (datetime.today()).strftime('%Y%m%d') # Used to create the filename

#Iterating through email items in outlook folder  

for message in messages:
    row = list()
    try:
        row.append(message.Subject)
        row.append(message.Categories)
        row.append(message.Sender)
        row.append(message.Sender.Address)
        row.append(message.To)
        row.append(message.SentOn)
        row.append(message.CC)
        row.append(message.BCC)
                
 
        # Stores the data in a list
        data_set.append(row)
    except AttributeError as ex:
      print('Error', ex, 'skipping message', message)
      continue
                
# Print out the result to a csv with headers
with open(date_id + "_"+ 'outlook_Data.csv', 'w', newline='', encoding='utf-8') as csv_file:
    headers = ['Subject', 'Category', 'From', 'To', 'Sent On', 'CC', 'BCC']
    wr = csv.writer(csv_file, delimiter=',')
    wr.writerow(headers)
    for line in data_set:
        wr.writerow(line)

総合生活情報サイト - OKWAVES
総合生活情報サイト - OKWAVES
生活総合情報サイトokwaves(オールアバウト)。その道のプロ(専門家)が、日常生活をより豊かに快適にするノウハウから業界の最新動向、読み物コラムまで、多彩なコンテンツを発信。