Получать только массу писем, писем из текстовых файлов - PullRequest
0 голосов
/ 19 февраля 2019

Я хочу удалить все из, to, cc, отправленные теги темы из этого текстового документа и сохранить только тело письма, чтобы я мог использовать это для обобщения содержимого документа.Каков наилучший способ сделать это в Python.Я думаю, что для этого лучше сначала выполнить извлечение, а затем использовать предварительную обработку.Также прикрепляя код здесь.Так что если кто-нибудь может подсказать, как это сделать, было бы очень полезно.Полезная нагрузка и ismultipart часть файла не выполнены должным образом, и вот где я сомневаюсь и поэтому прокомментировал эту часть и нуждаюсь в помощи.

Прикрепление кода и файла .txt ниже для справки.

import os, sys, csv
import glob
import re
import email
#from tika import parser
import warnings
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
from gensim.summarization import summarize, keywords

# Set path to directory where files are
dirs = 'C:\\Users\\Lenovo\\.spyder-py3\\Testing\\'
#os.chdir(dirs)
for filename in glob.glob(os.path.join(dirs, '*.txt')):
    try:
        for files in filename:
            file = open(filename, 'r', encoding ='utf-8')
            filecontents = file.read()
            filecontents = re.sub(r'\s+', ' ', filecontents)
            print(filecontents)
            filecontents = filecontents.strip('\n')
            b = email.message_from_string(filecontents)# NEED
            if b.is_multipart():#HELP
                for payload in b.get_payload():#HERE
                    # if payload.is_multipart(): ...#SO
                    print (payload.get_payload())#COMMENTED
            else:#
                print (b.get_payload())#
            summary = summarize(filecontents, ratio =0.10)
            print(summary)
            kw = keywords(filecontents, words=15)
            print(kw)
            break
            #writer.writerow([file, summary, kw])
    except Exception as e:
        pass

Текстовый файл

 Stephanie /ANN

From: Mr.A,  <.Mr.A@abc.com>
Sent: Wednesday, July 25, 2018 2:27 PM
To: , Tim /ANN; Abd, May /ANN
Cc: Mr.A, ; Theoder Jerry,
Subject: [EXTERNAL] RE:  Holdings: XXXX SPA – mfno.1322

Dear Dr. Tim A. , 

The option-2 is fine. By the way, we had received in the past Letter of Authorization for many companies other 
than Spa and I guess Xxxx does not do bANNiness with them either. If yes, then need to submit withdrawal 
of Letter of Authorization for those companies and send a Letter of Authorization for spa. stating for any 
applications submitted. We will send an administrative filing issue letter for both the holder and the agent.  



Thank you! 

Regards, 
 Mr.A 
PRODUCT Master File 
CDER 



Currently, there is no requirement to submit or resubmit NAs in any electronic format.  However, starting May 5, 2018, 
new NAs, as well as any submissions to the existing NAs mANNt be submitted electronically in legal (electronic Common 
Technical Document) format specified by GROUP A in the legal guidance. NA submissions that are not submitted in legal 
format after this date may be subject to rejection. For more information please check the NA website 
www.GROUP A.gov/abc/bca 


This communication is an informal communication consistent with which represents my best judgment 
at this time, but does not constitute an advisory opinion, does not necessarily represent the formal position of the 
GROUP A, and does not bind or otherwise obligate or commit the agency to the views expressed. This communication, 
including any attachments, is intended only for the person or entity to which it is addressed and may contain 
confidential material. Any review, retransmission, distribution or other ANNe of this information by persons or entities 
other than the intended recipient is prohibited. If you received this in error, please destroy any copies, contact the 
sender and delete the material from any computer. Thank you. 

From: Tim.@xxxx.com [mailto:Tim.@xxxx.com]  
Sent: Wednesday, July 25, 2018 2:10 PM 
To: Mr.A,  <.Mr.A@abc.com> 
Cc: May.Abd@xxxx.com 
Subject: RE: Holdings: XXXX SPA ‐ dm 013383 

Dear , 


XXXX



2

Thanks for your phone call to clarify your needs and to understand the situation. I have confirmed that Xxxx only does 
direct bANNiness for test  S intermediate with b. and not with the other companies (e, 
x, etc.) that are secondary companies. Based on our discANNsion, I believe that we do not need to 
provide QAs for these secondary companies or mention them in our NA file as they would be covered under a 
separate QA  S.p.A. to them. If this is correct, then I believe you mentioned that we have two options as 
described below: 

Option 1: We can issue a separate QA for each . NA to be specific on which NA is being cross‐referenced 
to our NA 13383. 

Option 2: We can do a single QA for  and mention that they can cross‐reference any of their NAs. This 
would allow them to cross‐reference any of their 

If I have misunderstood or am incorrect in my response and we need to discANNs further, please let me know. 

If not, when you issue your request, can you please send to me and May Abd by email? 

Kind regards. 

Tim 

Tim A. , BsC 
Director, YY SERVICES) 
Xxxx ANN 
Phone/FAX: 2312333 
Cell: 23312123131 
Email: tim.@xxxx.com 



From: , Tim /ANN  
Sent: Monday, July 23, 2018 7:05 AM 
To: 'Mr.A, ' 
Cc: Abd, May /ANN 
Subject: RE: [EXTERNAL] Holder: XXXX SPA - NA 013383 

Dear , 

May is now on vacation and I am covering for her during her absence. Is there a good time to call you today or later this 
week? Please let me know and we can schedule or please call my cell phone 21313131231 at your convenience. 

Kind regards. 

Tim 

Tim A. , MSC 
Director, PQR 
Xxxx 
Phone/FAX: 2312313313 
Cell: 3142342424 
Email: tim.@xxxx.com 



XXXX



3


‐‐‐‐‐‐‐‐‐‐ Forwarded message ‐‐‐‐‐‐‐‐‐‐ 
From: "Mr.A, " <.Mr.A@abc.com> 
Date: Jul 20, 2018 9:01 AM 
Subject: [EXTERNAL] Holder: XXXX SPA ‐ NA 013383 
To: "TRETE/ANN" <May.Abd@xxxx.com> 
Cc: "mno.com> 

Dear May Abd, 

. I need to talk to you on this.  

Thank you! 

Regards, 
 Mr.A 
PRODUCT Master File 
CDER 


Currently, there is no requirement to submit or resubmit NAs in any electronic format.   
format after this date may be subject to rejection. For more information please check the NA website 
www.GROUP A./cder/NA   


This communication is an informal communication  which represents my best judgment 
at this time, but does not constitute an advisory opinion, does not necessarily represent the formal position of the 
GROUP A, and does not bind or otherwise obligate or commit the agency to the views expressed. This communication, 
including any attachments, is intended only for the person or entity to which it is addressed and may contain 
confidential material. Any review, retransmission, distribution or other ANNe of this information by persons or entities 
other than the intended recipient is prohibited. If you received this in error, please destroy any copies, contact the 
sender and delete the material from any computer. Thank you. 


XXXX

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Не совсем понятно, с какой частью кода вам нужна помощь, что вы хотите от нее делать вместо того, что она делает в настоящее время, или как правильно передать результаты для дальнейшей обработки.

Однако,Отмечу, что у вашего кода есть ряд проблем.

  • Вы не можете прочитать сообщение электронной почты в виде текста UTF-8.Независимо от расширения файла сообщение RFC822 представляет собой просто последовательность байтов.Традиционная электронная почта может входить в большое количество различных кодировок, и если вы попытаетесь привести ее к UTF-8, вы столкнетесь с UnicodeDecodeError s и другими препятствиями.
  • Как всегда, одеяло except Exception:это серьезная ошибкаВозможно, вы используете это только для отладки, но на самом деле это затрудняет отладку.
  • Типичные современные сообщения электронной почты содержат довольно сложные структуры тела MIME, которые вы должны проанализировать в контексте, прежде чем решить, какие из них вы на самом делехочу обработать.Одним из распространенных явлений является multipart/alternative, когда одно и то же сообщение отображается в разных форматах, так что получатели могут решить, хотят ли они прочитать его как HTML, обычный текст или, иногда, возможно, PDF или RTF или одно изображение или что-то еще, в зависимости отпо заявке.Кроме того, HTML-структуры часто состоят из нескольких частей, потому что основной HTML-код хочет добавить небольшие изображения, которые также предоставляются в структуре MIME (логотип компании, анимированные смайлики и другие оскорбления для читателя).Возможно, смотрите также Что такое "части" в многочастном электронном письме?

Еще одно осложнение этого ответа состоит в том, что библиотека email Python претерпела капитальный ремонт сравнительно недавно.Новая функциональность была введена экспериментально в Python 3.3, но стала документированной и версией по умолчанию в 3.6.Большая часть кода, который вы обнаружите в дикой природе, будет использовать средства, предшествующие версии 3.6, но в будущем вы, вероятно, захотите использовать новый и улучшенный API.

С устаревшим API ваш код может выглядетьчто-то вроде

from email import message_from_binary_file

for filename in glob.glob(os.path.join(dirs, '*.txt')):
    # Not useful; we already have a filename
    #for files in filename:
    # Open in binary mode, don't try to guess encoding
    # Use a context manager so we don't leave the file open
    with open(filename, 'rb') as file:
        # Just let the email library take it from here
        #filecontents = file.read()
        #filecontents = re.sub(r'\s+', ' ', filecontents)
        #print(filecontents)
        #filecontents = filecontents.strip('\n')
        b = email.message_from_binary_file(file)
    if b.is_multipart():
        # There are a number of things you could do to pick out
        # one or more payloads for analysis, but let's just take
        # the first text/plain part and call it "main_part"
        for part in b.walk()
            if part.get_content_type() == 'text/plain':
                main_part = part.get_payload()
                break
    else:
        main_part = b.get_payload()
    summary = summarize(main_part, ratio =0.10)
    print(summary)
    kw = keywords(main_part, words=15)
    print(kw)

Чтобы использовать новый API 3.6+, вам нужно адаптировать его к чему-то вроде

from email.policy import default as default_email_policy
...
    b = email.message_from_binary_file(file, policy=default_email_policy)
    main_part = b.get_body(['related', 'plain', 'html'])

Это приведет к созданию нового объекта email.message.EmailMessage, который имеет несколько инойметоды и поведение, отличное от класса email.message.Message.Документация предполагает, что, возможно, однажды по умолчанию будет передано значение по умолчанию policy, после чего старый код переключится на новое поведение (но также, вероятно, некоторое количество неприятных сюрпризов и откровенных поломок).

Примечаниетакже get_body() метод , который является новым в 3.6 и который позволяет вам легко выбрать «вероятную основную часть»;хотя, если нет части text/plain, приведенный выше код вернется к HTML, который затем потребуется обработать, чтобы извлечь фактический текст (см. Beautifulsoup возможно?)

Не существует технического, надежного и надежного способа отделить шаблон (заголовки, подписи и т. Д.) От реального содержимого в электронной почте.Некоторые клиенты электронной почты в формате HTML могут предоставлять подсказки в сгенерированном сообщении о том, что <div> содержит то, что набрал пользователь, но в общем случае вам просто нужно поднять брови в (честно говоря, безнадежной) эвристике.

0 голосов
/ 20 февраля 2019

Если вы хотите удалить из письма только теги «Откуда», «Отправлено», «Копия», «Тема» и «Переадресовано», вы можете использовать регулярное выражение.

import re

with open('email_input.txt', 'r') as input:
   lines = input.readlines()
   no_new_lines = [i.strip() for i in lines]
   for line in no_new_lines:
      email_component = re.compile(r'((From:|Sent:|To:|Cc:|Subject:|Forwarded message).*)', re.IGNORECASE)
      remove_component = re.findall(email_component, line)
      if remove_component:
         print(line)

         # output
         ‐‐‐‐‐‐‐‐‐‐ Forwarded message ‐‐‐‐‐‐‐‐‐‐
         From: Mr.A,  <.Mr.A@abc.com>
         Sent: Wednesday, July 25, 2018 2:27 PM
         To: , Tim /ANN; Abd, May /ANN
         Cc: Mr.A, ; Theoder Jerry,
         Subject: [EXTERNAL] RE:  Holdings: XXXX SPA – mfno.1322

Относительно удаления контента после слова "regards".Я не добавил это к своему регулярному выражению, потому что электронные письма могут быть подписаны несколькими способами.Вот некоторые из наиболее распространенных способов:

Best,
Best regards,
Best wishes,
Fond regards,
Kind regards,
Regards,
Sincerely,
Sincerely yours,
Thank you,
With appreciation,
With gratitude,
Yours sincerely,  

ОБНОВЛЕННЫЙ ОТВЕТ ОДИН

Приведенный ниже обновленный ответ очищает еще немного ввода электронной почты, но требуется дополнительная очистка.

import re

with open('email_input.txt', 'r') as input:
   lines = input.readlines()

   # Remove some of the extra lines
   no_new_lines = [i.strip() for i in lines]

   # regex to catch header lines
   email_component = re.compile(r'((From:|Sent:|To:|Cc:|Subject:|Date:|Forwarded message).*)', re.IGNORECASE)
   remove_headers = [x for x in no_new_lines if not email_component.findall(x)]

   # regex to catch greeting lines
   greeting_component = re.compile(r'(Dear.*)', re.IGNORECASE)
   remove_greeting = [x for x in remove_headers if not greeting_component.findall(x)]

   # regex to catch lines with contact details
   contact_component = re.compile(r'(Phone.*:)|(Cell:.*)|(Email:.*)', re.IGNORECASE)
   remove_contacts = [x for x in remove_greeting if not contact_component.findall(x)]

    # regex to catch lines with salutation
    email_salutation_component = re.compile(r'Best,(.*?)|Best regards,(.*?)|Best wishes,(.*?)|Fond regards,(.*?)|'
                                        r'Kind regards(.*?)|Regards,(.*?)|Sincerely,(.*?)|Sincerely yours,(.*?)|'
                                        r'Thank you,(.*?)|With appreciation,(.*?)|Yours sincerely,(.*?)', re.IGNORECASE)

    remove_salutations = [x for x in remove_contacts if not email_salutation_component.findall(x)]

    # do something else

ОБНОВЛЕННЫЙ ОТВЕТ ДВА

В обновленном ответе ниже используется библиотека электронной почты python.Мой входной файл был оригинальным сообщением электронной почты, полученным из моего почтового клиента.Используя приведенный ниже код, я смог извлечь текст каждого сообщения электронной почты, которое я пробовал.Я также протестировал модуль gensim, и он работал правильно.

import email
from gensim.summarization import summarize, keywords

with open('email_input.txt', 'r') as input:
  email_body = ''
  raw_message = input.read()

  # Return a message object structure from a string
  msg = email.message_from_string(raw_message)

  # iterate over all the parts and subparts of a message object tree
  for part in msg.walk():

    # Return the message’s content type.
    if part.get_content_type() == 'text/plain':
        email_body = part.get_payload()

  summary = summarize(email_body, ratio=0.10)
  print(summary)

  kw = keywords(email_body, words=15)
  print(kw)

ФИНАЛЬНЫЙ ОТВЕТ

Это мой окончательный ответ на этот вопрос.Надеюсь, один из этих 4 ответов соответствует вашим требованиям.

Вы должны будете сделать небольшую очистку вывода, потому что я не знаю всех ваших требований.

with open('email_input.txt') as infile:
  # Boolean state variable to keep track of whether we want to be printing lines or not
  lines_to_keep = False
  for line in infile:

    # Look for lines that start with a greeting
    if line.startswith("Dear"):
      # set lines_to_keep true and start capturing lines
      lines_to_keep = True

    # Look for lines that start with a salutation
    elif line.startswith("Regards") or line.startswith("Kind regards"):
        # set lines_to_keep false and stop capturing lines
        lines_to_keep = False


    if lines_to_keep:
        greeting_component = re.compile(r'(Dear.*)', re.IGNORECASE)
        remove_greeting = re.match(greeting_component, line)
        if not remove_greeting:
            print (line.rstrip('\n'))
            # output 
            The option-2 is fine. By the way, we had received in the past Letter of Authorization for many companies other than Spa and I guess Xxxx does not do bANNiness with them either. If yes, then need to submit withdrawal of Letter of Authorization for those companies and send a Letter of Authorization for spa. stating for any applications submitted. We will send an administrative filing issue letter for both the holder and the agent.  

           more here....
...