Beispiel #1
0
def main():
    project_dir = Path(__file__).parents[1]
    token_dir = project_dir.joinpath('token')
    token_paths = {
        'pickle_path': token_dir.joinpath('token.pickle'),
        'json_path': token_dir.joinpath('client_id.json')
    }
    # 必須ファイルなければ終了
    if not required_files_exists(token_dir, token_paths):
        sys.exit()

    g_mail = Gmail(token_paths)
    label_list = g_mail.label_list()
    labels = [label['name'] for label in label_list if label['type'] == 'user']

    filter_frame = [[
        sg.OptionMenu(['from', 'to', 'subject'],
                      disabled=True,
                      key='filter_type',
                      size=(5, 1)),
        sg.InputText(disabled=True,
                     key='filter_txt',
                     default_text='',
                     size=(20, 1))
    ]]
    layout = [[sg.Text('ラベル'),
               sg.Combo(labels, key='label', size=(25, 1))],
              [sg.Checkbox('フィルターを作成する', key='is_filter', enable_events=True)],
              [sg.Frame('フィルター', filter_frame, key='filter')],
              [
                  sg.Column([[sg.Button('作成', key='create', size=(6, 1))]],
                            justification='right')
              ]]

    window = sg.Window('GMail Filter',
                       layout,
                       finalize=True,
                       icon='icon/filtan.ico')

    while True:
        event, values = window.read()
        # ×ボタン押下(None)で閉じる
        if event is None:
            break
        else:
            input_label = values['label']
            input_filter_type = values['filter_type']
            input_filter_txt = values['filter_txt']

        if event == 'is_filter':
            # フィルターチェックボックスでフィルター入力可・不可切り替え
            if values['is_filter'] is True:
                window['filter_type'].update(disabled=False)
                window['filter_txt'].update(disabled=False)
            else:
                window['filter_type'].update(disabled=True)
                window['filter_txt'].update('', disabled=True)
        elif event == 'create':
            # 作成ボタン押下禁止
            window['create'].update(disabled=True)
            success_msg = ''
            error_msg = 'ラベルを入力してください。\n' if input_label == '' else ''
            # チェックボックス.get() => True: 1, False: 0
            if window['is_filter'].get() == 1 and input_filter_txt == '':
                error_msg += 'フィルターを入力してください。'

            if error_msg != '':
                sg.Popup('Error', error_msg)
            else:
                # チェックボックス.get() => True: 1, False: 0
                if window['is_filter'].get() == 1:
                    # 入力したラベル名からラベルID取得
                    label_id = ''
                    for label in label_list:
                        if label['name'] == values['label']:
                            label_id = label['id']
                            break

                    # 既存のラベルじゃなければ作成
                    if label_id == '':
                        label_result = g_mail.create_label(input_label)
                        if type(label_result) is dict:
                            success_msg += 'ラベル「{}」の作成に成功しました。\n'.format(
                                input_label)
                            # ラベルリスト更新
                            labels = [
                                label['name'] for label in g_mail.label_list()
                                if label['type'] == 'user'
                            ]
                            window['label'].update(value=label_result['name'],
                                                   values=labels)
                            # フィルター作成
                            filter_result = g_mail.create_filter(
                                input_filter_type, input_filter_txt,
                                label_result['id'])
                        else:
                            filter_result = None
                            error_msg += label_result
                    else:
                        filter_result = g_mail.create_filter(
                            input_filter_type, input_filter_txt, label_id)

                    if type(filter_result) is dict:
                        success_msg += 'フィルター「{}:{}」の作成に成功しました。\n'.format(
                            input_filter_type, input_filter_txt)
                    else:
                        error_msg += filter_result
                else:
                    if input_label in labels:
                        error_msg += 'そのラベル名はすでにあります。\n別の名前を付けてください。'
                    else:
                        label_result = g_mail.create_label(input_label)
                        if label_result['name'] == values['label']:
                            success_msg = 'ラベル「{}」の作成に成功しました。'.format(
                                label_result['name'])
                            labels = [
                                label['name'] for label in g_mail.label_list()
                                if label['type'] == 'user'
                            ]
                            window['label'].update(value=label_result['name'],
                                                   values=labels)
                # ポップアップ表示
                if success_msg:
                    sg.Popup('Success', success_msg)
                elif error_msg:
                    sg.Popup('Error', error_msg)
        # ボタン押下禁止解除
        window['create'].update(disabled=False)

    window.close()
class FalconClient:
    def __init__(self, email):
        self.email = email
        self.gmail = Gmail()
        self.gmail.auth(self.email, method='Desktop')

        self._labels = None

    def get_labels(self):
        if self._labels is None:
            self._labels = {
                i['id']: i
                for i in self.gmail.list_labels()['labels']
            }
        return self._labels

    def get_label_by_name(self, name):
        labels_by_name = {i['name']: i for i in self.get_labels().values()}
        return labels_by_name.get(name, None)

    def create_label(self, name):
        created = False
        if self.get_label_by_name(name) is None:
            try:
                label_body = {
                    'name': name,
                    'type': 'user',
                    'labelListVisibility': 'labelShow',
                    'messageListVisibility': 'show',
                    'messagesTotal': 0,
                    'threadsUnread': 0,
                    'messagesUnread': 0,
                    'threadsTotal': 0,
                    'color': {
                        "textColor": '#000000',
                        "backgroundColor": '#ffffff',
                    }
                }

                label = self.gmail.create_label(label_body)
                self._labels[label['id']] = label

                created = True
            except Exception as e:
                logging.exception(e)

        return created

    def save_mails(self, filter_q):
        start_time = datetime.now()
        base_dir = os.path.join(root_dir, 'data', self.email)

        # load state file
        state_file_path = os.path.join(base_dir, 'state.pickle')
        os.makedirs(os.path.dirname(state_file_path), exist_ok=True)
        state = {}
        if os.path.exists(state_file_path):
            with open(state_file_path, 'rb') as fp:
                state = pickle.load(fp)

        query = filter_q if filter_q is not None else ''
        last_modified_date = state.get('lastModifiedDate', None)
        if last_modified_date is not None:
            query += f" after:{last_modified_date.strftime('%Y/%m/%d')}"

        query = query.strip()
        print(f'Modified mail listing query [{query}]')

        # do my thing with mails
        mails = self.gmail.list_mails(query=query,
                                      max_pages=10000,
                                      include_spam_and_trash=True)
        print(f'Number of mails for [{self.email}] : [{len(mails)}].')

        for index, mail in enumerate(mails, 0):
            mail_id = mail['id']
            thread_id = mail['threadId']

            mail_path = os.path.join(base_dir, thread_id, mail_id, 'mail.json')
            if os.path.exists(mail_path):
                print(
                    f'Skipping mail #[{index}], Id [{mail_id}], ThreadId [{thread_id}].'
                )
                continue

            print(f'Mail #[{index}], Id [{mail_id}], ThreadId [{thread_id}].')

            mail_body = self.gmail.get_mail(mail_id)

            os.makedirs(os.path.dirname(mail_path), exist_ok=True)
            with open(mail_path, 'w') as fp:
                json.dump(mail_body, fp)

            # Avoid too many api hits
            time.sleep(0.5)

        # update state
        state['lastModifiedDate'] = start_time
        with open(state_file_path, 'wb') as fp:
            pickle.dump(state, fp)