ó
    ×[.j¤a  ã                  ó  • S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKrSSKJrJr  SSKJr  SSKJr  SSKJr  SSKJrJrJrJrJ r J!r!J"r"  SS	K#J$r$J%r%  \RL                  " \'5      r(\RR                  " S
5      r*    S$S jr+S%S jr,S r-\-S&S j5       r.S r/S r0S r1S r2S r3S r4S r5S r6S r7S r8S r9S r:/ / 4S jr;S r<S'S jr=S r>S r?S  r@S! rAS" rBS(S# jrCg))aR  
Copyright 2016 Fedele Mantuano (https://twitter.com/fedelemantuano)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
é    )ÚannotationsN)ÚCounterÚ
namedtuple)ÚHeaderParseError)Údecode_header©Ú	normalize)Ú_CLAUSE_SPLITTERÚ_DATE_REÚ_ENVELOPE_FROM_REÚ_SENDGRID_DATE_REÚADDRESSES_HEADERSÚJUNK_PATTERNÚOTHERS_PARTS)ÚMailParserOSErrorÚMailParserReceivedParsingErrorzB"([^"]*?)"\s*<([^>]+)>|([^<,]*?)\s*<([^>]+)>|([^\s,<>]+@[^\s,<>]+)c                ó&  • U c  / $ [        U [        R                  R                  5      (       a  [	        U R                  5       5      n O [        U [        5      (       d  [        U 5      n [        R                  R                  U /SS9nU R                  5       (       Gas  [        S U 5       5      (       Ga[  / n[        R                  U 5       GH  nUR                  S5      (       aO  UR                  UR                  S5      R                  5       UR                  S5      R                  5       45        Mi  UR                  S5      (       aO  UR                  UR                  S5      R                  5       UR                  S5      R                  5       45        MÎ  UR                  S5      (       d  Mæ  UR                  S	UR                  S5      R                  5       45        GM     U(       a"  [        R!                  S
U [#        U5      5        U$ U$ )uH  
Parse email addresses from a raw address header with a fallback for
RFC-non-compliant but real-world-common formats.

RFC 5322 Â§3.4 requires the display name (phrase) before an angle-bracket
address to consist only of printable ASCII characters that are *not*
special.  The ``@`` character is special, so a header such as::

    From: alice@example.com <bob@example.com>

is technically non-conforming because the display name contains an
unquoted ``@``.  Python's ``email.utils.getaddresses`` with
``strict=True`` (hardened against CVE-2023-27043) correctly returns
``[('', '')]`` for this input, making the real sender invisible.

mail-parser is a *security / forensics* tool, not an MTA.  Silently
discarding an address because its display name happens to look like an
e-mail address would hide relevant forensic information from analysts â€”
the very opposite of what the tool is for.  We therefore bypass strict
RFC compliance by applying a regex-based fallback whenever the strict
parser yields only empty addresses, so that analysts always see the value
that was actually present in the header.

Args:
    raw_header (str | email.header.Header | None): raw value of an
        address header (e.g. ``From``, ``To``, ``CC`` â€¦). Accepts a
        plain ``str``, an ``email.header.Header`` instance (returned
        by ``email.message.Message.get`` for headers containing
        RFC 2047 encoded-words such as non-ASCII display names), or
        ``None``.

Returns:
    list[tuple[str, str]]: list of ``(display_name, email_addr)`` tuples.
        ``display_name`` is an empty string when absent.
T)Ústrictc              3  ó4   #   • U  H  u  pU(       + v •  M     g 7f©N© )Ú.0Ú_Úaddrs      ÚM/home/mande/repo/quber/.venv/lib/python3.13/site-packages/mailparser/utils.pyÚ	<genexpr>Ú get_addresses.<locals>.<genexpr>Ž   s   é € Ð!Aº&©w¨q d§(¡(º&ùs   ‚é   é   é   é   é   Ú z\Strict address parsing yielded empty results for %r; regex fallback recovered %d address(es))Ú
isinstanceÚemailÚheaderÚHeaderÚdecode_header_partÚencodeÚstrÚutilsÚgetaddressesÚstripÚallÚ_ADDR_FALLBACK_REÚfinditerÚgroupÚappendÚlogÚdebugÚlen)Ú
raw_headerÚparsedÚresultsÚms       r   Úget_addressesr:   P   s�  € ðd ÑØˆ	Ü�*œeŸl™l×1Ñ1×2Ñ2Ü'¨
×(9Ñ(9Ó(;Ó<‰
Ü˜
¤C×(Ñ(Ü˜“_ˆ
ä�[‰[×%Ñ% z l¸4Ð%Ð@€Fð
 ×Ñ×ÒœcÑ!A¹&Ó!A×AÒAØˆÜ"×+Ñ+¨J×7ˆAØ�w‰w�q�z‰zØ—‘ §¡¨£
× 0Ñ 0Ó 2°A·G±G¸A³J×4DÑ4DÓ4FÐGÖHØ—‘˜—‘Ø—‘ §¡¨£
× 0Ñ 0Ó 2°A·G±G¸A³J×4DÑ4DÓ4FÐGÖHØ—‘˜—“Ø—‘  A§G¡G¨A£J×$4Ñ$4Ó$6Ð7×8ñ 8ö Ü�I‰Ið:àÜ�G“ô	ð ˆNà€Mó    c                óF  • U(       a  [         R                  " U5      nO[         R                  " 5       nUR                  U 5        [         R                  " [        R
                  5      n[         R                  " S5      nUR                  U5        UR                  U5        U$ )zŽ
This function returns a custom logger.
:param level: logging level
:type level: str
:param name: logger name
:type name: str
:return: logger
z]%(asctime)s | %(name)s | %(module)s | %(funcName)s | %(lineno)d | %(levelname)s | %(message)s)	ÚloggingÚ	getLoggerÚsetLevelÚStreamHandlerÚsysÚstdoutÚ	FormatterÚsetFormatterÚ
addHandler)ÚlevelÚnamer3   ÚchÚ	formatters        r   Ú
custom_logrJ   £   sy   € ö Ü×Ò Ó%‰ä×ÒÓ!ˆØ‡L�L�ÔÜ	×	Ò	œsŸz™zÓ	*€BÜ×!Ò!ð	ó€Ið ‡O�O�IÔØ‡N�N�2ÔØ€Jr;   c                óF   ^ • [         R                  " T 5      U 4S j5       nU$ )z1NFC is the normalization form recommended by W3C.c                 ó(   >• [        ST" U 0 UD65      $ )NÚNFCr   )ÚargsÚkwargsÚfuncs     €r   ÚwrapperÚsanitize.<locals>.wrapperÃ   s   ø€ ä˜¡ dÐ 5¨fÑ 5Ó6Ð6r;   )Ú	functoolsÚwraps)rP   rQ   s   ` r   ÚsanitizerU   À   s'   ø€ ô ‡_‚_�TÓô7ó ð7ð €Nr;   c                ó  • U (       d
  [        5       $ [        U [        R                  R                  5      (       a  [        U 5      $ [        U [         5      (       a  U $  [        X5      $ ! [
        [        4 a    [        U SU5      s $ f = f)a  
Give as input raw data and output a str in Python 3.

Args:
    raw_data: bytes or str to convert to str
    encoding: string giving the name of an encoding
    errors: specifies the treatment of characters
        which are invalid in the input encoding

Returns:
    str
úutf-8)r*   r$   r%   r&   r'   ÚLookupErrorÚUnicodeDecodeError)Úraw_dataÚencodingÚerrorss      r   Úported_stringr]   Ê   su   € ö Ü‹uˆä�(œEŸL™L×/Ñ/×0Ñ0Ü�8‹}Ðä�(œC× Ñ Øˆð.Ü�8Ó&Ð&øÜÔ+Ð,ó .Ü�8˜W fÓ-Ò-ð.ús   Á
A) Á)B	ÂB	c                ó8  • U (       d
  [        5       $ [        5       n [        U 5       H  u  p#U(       a  UOSnU[        X#S5      -  nM!     UR                  5       $ ! [        [        4 a.    [
        R                  SU  35        X-  n UR                  5       $ f = f)zl
Given a raw header returns a decoded header

Args:
    header (string): header to decode

Returns:
    str
rW   ÚignorezFailed decoding header part: )r*   r   r]   r   ÚUnicodeErrorr3   Úerrorr-   )r&   ÚoutputÚdÚcs       r   r(   r(   é   s‘   € ö Ü‹uˆä‹U€FðÜ! &Ö)‰DˆAÞ‘˜GˆAØ”m A¨(Ó3Ñ3ŠFñ *ð �<‰<‹>Ðøô	 œlÐ+ó Ü�	‰	Ð1°&°Ð:Ô;ØÑ‰à�<‰<‹>Ðð	ús   �.A Á,BÂBc                ó   • [        U SSS9$ )zxOpen a file with UTF-8 encoding and ignore errors.

Args:
    file_: path to the file to open

Returns:
    file object
rW   r_   )r[   r\   )Úopen)Úfile_s    r   Úported_openrh     s   € ô � °Ñ9Ð9r;   c                ó¤   •  U R                  U5      [        U5      -   nU R                  X#5      nXU R                  5       $ ! [         a     g f = fr   )Úindexr5   r-   Ú
ValueError)ÚtextÚfirst_tokenÚ
last_tokenÚstartÚends        r   Úfind_betweenrq     sR   € ðØ—
‘
˜;Ó'¬#¨kÓ*:Ñ:ˆØ�j‰j˜Ó+ˆØ˜#ˆ×$Ñ$Ó&Ð&øÜó Ùðús   ‚?A Á
AÁAc                ó(  • [        SS5      n[        U [        5      (       d  U R                  S5      n [        R
                  " 5       nUR                  U 5        UR                  5       n[        R                  " 5       nUR                  U 5        UR                  5       n[        R                  " 5       nUR                  U 5        UR                  5       n[        R                  " 5       nUR                  U 5        UR                  5       nU" X#XE5      $ )z”
This function return the fingerprints of data.

Args:
    data (string): raw data

Returns:
    namedtuple: fingerprints md5, sha1, sha256, sha512
ÚHasheszmd5 sha1 sha256 sha512rW   )r   r$   Úbytesr)   ÚhashlibÚmd5ÚupdateÚ	hexdigestÚsha1Úsha256Úsha512)ÚdataÚhashesrv   ry   rz   r{   s         r   Úfingerprintsr~     sÒ   € ô ˜Ð":Ó;€Fä�dœE×"Ñ"Ø�{‰{˜7Ó#ˆô �+Š+‹-€CØ‡J�JˆtÔØ
�-‰-‹/€Cô �<Š<‹>€DØ‡K�K�ÔØ�>‰>Ó€Dô �^Š^Ó€FØ
‡M�M�$ÔØ×ÑÓ€Fô �^Š^Ó€FØ
‡M�M�$ÔØ×ÑÓ€Fá�#˜VÓ,Ð,r;   c                 ó^   • [         R                  " SS9u  p[        R                  " U 5        U$ )aI  
Create an empty temporary file to hold a converted Outlook email.

The OS-level file handle is closed immediately; callers write to the
returned path with their own handle (a subprocess ``--outfile`` for
``msgconvert`` or a plain ``open`` for the pure-Python backend).

Returns:
    str: path of the new temporary ``.eml`` file
Úoutlook_)Úprefix)ÚtempfileÚmkstempÚosÚclose)ÚhandleÚpaths     r   Ú_new_outlook_tempfilerˆ   A  s'   € ô ×#Ò#¨:Ñ6�L€FÜ‡H‚HˆVÔØ€Kr;   c                ó*  • SSK n[        R                  S5        UR                  U 5      n [	        USS5      nUc&  [        SU < S[        U5      R                   S35      eU" 5       nUR                  SS	5       S
UR                  SS	5       3R                  5       n[        5       n[        US5       nUR                  UR                  5       5        SSS5        Xe4UR                  5         $ ! , (       d  f       N!= f! UR                  5         f = f)aÐ  
Convert an Outlook ``.msg`` file to ``.eml`` using the pure-Python
``extract-msg`` library (no external Perl tool required).

The ``extract_msg`` import is performed lazily inside this function so
that the package keeps importing with zero runtime dependencies when
the optional ``outlook`` extra is not installed.

Args:
    fp (string): file path of the Outlook ``.msg`` mail

Returns:
    tuple: ``(eml_path, info)`` where ``eml_path`` is the path of the
    converted ``.eml`` file and ``info`` is a short descriptive string

Raises:
    ImportError: if the ``extract-msg`` library is not installed
    MailParserOSError: if the ``.msg`` is not a convertible email
        message (e.g. a contact or calendar item)
r   Nz1Started converting Outlook email with extract-msgÚasEmailMessagezOutlook file z* is not a convertible email message (type Ú)ÚFromr#   z | ÚSubjectÚwb)Úextract_msgr3   r4   ÚopenMsgÚgetattrr   ÚtypeÚ__name__Úgetr-   rˆ   rf   ÚwriteÚas_bytesr…   )Úfpr�   ÚmsgÚas_email_messageÚemlÚinfoÚtempÚfs           r   Úextract_msg_convertrž   Q  sú   € ó* ä‡I�IÐAÔBØ
×
Ñ
˜bÓ
!€Cðô # 3Ð(8¸$Ó?ÐØÑ#Ü#Ø ™vð &!Ü!% c£×!3Ñ!3Ð 4°Að7óð ñ Ó ˆØ—'‘'˜& "Ó%Ð& c¨#¯'©'°)¸RÓ*@Ð)AÐB×HÑHÓJˆÜ$Ó&ˆÜ�$˜Ô Ø�G‰G�C—L‘L“NÔ#÷ àˆzà�	‰	�÷	 Õûð 	�	‰	�ús$   ¬BD  Â4 C/Ã
D  Ã/
C=Ã9D  Ä Dc                ó¢  • [         R                  S5        [        5       nSSX/n [        R                  " U[        R
                  [        R
                  [        R                  S9nUR                  5       u  pEXR                  S5      R                  5       4$ ! [         a+  nSU< 3n[         R                  U5        [        U5      eSnAff = f)a#  
Exec msgconvert tool, to convert msg Outlook
mail in eml mail format

Args:
    email (string): file path of Outlook msg mail

Returns:
    tuple with file path of mail converted and
    standard output data (str)

Raises:
    MailParserOSError: if the ``msgconvert`` tool is not installed
z Started converting Outlook emailÚ
msgconvertz	--outfile)ÚstdinrB   ÚstderrrW   zÊCannot convert Outlook .msg: no conversion backend available. Install pure-Python support with 'pip install mail-parser[outlook]', or install the 'msgconvert' Perl tool (libemail-outlook-message-perl). N)r3   r4   rˆ   Ú
subprocessÚPopenÚPIPEÚDEVNULLÚcommunicateÚdecoder-   ÚOSErrorÚ	exceptionr   )r%   rœ   ÚcommandÚoutÚ
stdoutdatar   ÚeÚmessages           r   r    r    }  sÂ   € ô ‡I�IÐ0Ô1Ü Ó"€DØ˜[¨$Ð6€Gð8Ü×ÒØÜ—/‘/Ü—?‘?Ü×%Ñ%ñ	
ˆð& Ÿ™Ó)‰ˆ
Ø×&Ñ& wÓ/×5Ñ5Ó7Ð7Ð7øô ó 	)ð0ð 12©uð	6ð 	ô 	�‰�gÔÜ Ó(Ð(ûð	)ús   ¦AB Â
CÂ#&C	Ã	Cc                ój  • 0 n[         R                  " U 5      nU(       a(  UR                  S5      US'   U SUR                  5        nOG[        R                  " U 5      nU(       a(  UR                  S5      US'   U SUR                  5        nOU n[
        R                  " U5      nSnUS-   [        U5      :  a§  XV   R                  5       nXVS-      R                  5       nUS-  nUS;   aA  [        R                  " U5      n	U	(       a#  U	R                  S5      XR                  SS5      '   O US:X  a  X�U'   OUS	:X  a  S	U;  a  X�U'   OX�U'   US-   [        U5      :  a  M§  S
 H‰  n
UR                  U
S5      nS Hn  u  pÍXÁ;  d  M  XÛR                  5       ;   d  M!  [        R                  " S[        R                  " U5      -   S-   U5      n	U	(       d  M[  U	R                  S5      X'   Mp     M‹     U(       d  SU -  n[        U5      e[         R#                  S[%        UR'                  5       5      5        U$ )uÂ  
Parse a single received header by tokenizing on RFC 5321 Â§4.4 keywords.

Uses a keyword-based splitter to divide the header into clauses
(from, by, via, with, id, for, envelope-from, envelope-sender),
then extracts the date from after the semicolon.

Arguments:
    received {str} -- single received header

Raises:
    MailParserReceivedParsingError -- Raised when a
        received header cannot be parsed

Returns:
    dict -- values by clause
r   ÚdateNr   )úenvelope-fromúenvelope-senderÚ-r   ÚforÚfrom)Úbyr¶   Úwithr#   ))Úenvelope_fromr²   )Úenvelope_senderr³   z(?i)z\s+<([^>]+)>z!Unable to match any clauses in %szParsed clauses: %s)r   Úsearchr1   ro   r   r
   Úsplitr5   Úlowerr-   r   Úreplacer”   ÚreÚescaper   r3   r4   ÚlistÚkeys)ÚreceivedÚvalues_by_clauseÚ
date_matchÚheader_bodyÚsg_matchÚpartsÚiÚkeywordÚvaluer9   Ú
clause_keyÚ
clause_valÚenv_keyÚenv_namer˜   s                  r   Úparse_receivedrÐ   ¨  s  € ð& Ðô —’ Ó*€JÞØ#-×#3Ñ#3°AÓ#6Ð˜Ñ àÐ3 ×!1Ñ!1Ó!3Ð4‰ô %×+Ò+¨HÓ5ˆÞØ'/§~¡~°aÓ'8Ð˜VÑ$Ø"Ð#5 X§^¡^Ó%5Ð6‰Kà"ˆKô ×"Ò" ;Ó/€Eð 	
€AØ
ˆa‰%”#�e“*Ó
Ø‘(—.‘.Ó"ˆØ˜!‘e‘×"Ñ"Ó$ˆØ	ˆQ‰ˆàÐ:Ó:ä!×(Ò(¨Ó/ˆAÞØ>?¿g¹gÀa»jÐ §¡°°cÓ!:Ñ;øØ˜ÓØ(-˜WÒ%Ø˜Óð Ð-Ó-Ø,1 Ñ)øà(-˜WÑ%ð' ˆa‰%”#�e“*Õ
ó0 -ˆ
Ø%×)Ñ)¨*°bÓ9ˆ
ó"
ÑˆGð Õ.°8×?OÑ?OÓ?QÕ3QÜ—I’IØœbŸiši¨Ó1Ñ1°OÑCØó�÷ �1Ø01·±¸³
Ð$Ó-ó"
ñ -ö Ø1°XÑ>ˆÜ,¨SÓ1Ð1ä‡I�IÐ"¤DÐ)9×)>Ñ)>Ó)@Ó$AÔBØÐr;   c           
     ó  • / nU  Vs/ s H-  n[         R                  " [        SU5      R                  5       PM/     n n[	        U 5      n[
        R                  SU 35        [        U 5       HY  u  pE[
        R                  SUS-    SU 35        [
        R                  SU< 35         [        U5      nUR                  U5        M[     [
        R                  S[	        U 5      < S	[	        U5      < 35        [	        U 5      [	        U5      :w  aB  [
        R                  S
[	        U 5      < S[	        U5      < SU < SU< 35        [        U 5      $ [        U5      $ s  snf ! [         a    UR                  SU05         GM  f = f)zº
This function parses the receiveds headers.

Args:
    receiveds (list): list of raw receiveds headers

Returns:
    a list of parsed receiveds headers with first hop in first position
Ú zNr. of receiveds. zParsing received r   Ú/zTry to parse Úrawzlen(receiveds) z, len(parsed) zlen(receiveds): z, len(parsed): z, receiveds: z,             parsed: )r¿   Úsubr   r-   r5   r3   r4   Ú	enumeraterÐ   r2   r   ra   Úreceiveds_not_parsedÚreceiveds_format)Ú	receivedsr7   rÉ   ÚnÚidxrÃ   rÄ   s          r   Úreceiveds_parsingrÜ      sG  € ð €FÙ?HÓIºy¸!”—’œ c¨1Ó-×3Ñ3Ö5¹y€IÐIÜˆI‹€AÜ‡I�IÐ" 1 #Ð&Ô'ä" 9Ö-‰ˆÜ�	‰	Ð% c¨A¡g Y¨a°¨sÐ3Ô4Ü�	‰	�M (¡Ð.Ô/ð	,ä-¨hÓ7Ðð �M‰MÐ*Ö+ñ .ô ‡I‚I´S¸¶^ÄSÈÅ[ÐQÔRä
ˆ9ƒ~œ˜V›Ó$ô 	�	Š	ô �9Ž~œs 6ž{«I²vð?ô	
ô
 $ IÓ.Ð.ô   Ó'Ð'ùò? Jøô .ó 	-à�M‰M˜5 (Ð+×,Ð,ð	-ús   ‡4EÂ(E!Å!FÆFc                ó  • [         R                  SU < 35        [        R                  R	                  U 5      nUc  [        SU < 35      e[         R                  SU< 35        [        R                  R                  U5      n[         R                  SU< 35        [        R                  R                  U[        R                  R                  5      nUS   (       a  US   S-  OSnUS n[         R                  S	U< 35        X44$ )
z+
Convert a mail date in a datetime object.
zDate to parse: zCannot parse date: zDate parsed: zDate parsed in timestamp: é	   g      ¬@r   z+.1fzCalculated timezone: )r3   r4   r%   r+   Úparsedate_tzrk   Ú	mktime_tzÚdatetimeÚfromtimestampÚtimezoneÚutc)r±   rc   ÚtÚdate_utcrã   s        r   Úconvert_mail_daterç   .  sÝ   € ô ‡I�I� ™xÐ(Ô)Ü�‰× Ñ  Ó&€AØ�yÜÐ.¨t©hÐ7Ó8Ð8Ü‡I�I�˜a™UÐ#Ô$Ü�‰×Ñ˜aÓ €AÜ‡I�IÐ*¨1©%Ð0Ô1Ü× Ñ ×.Ñ.¨q´(×2CÑ2C×2GÑ2GÓH€HØ ! !§ˆq�‰t�fŠ}¨!€HØ˜4�€HÜ‡I�IÐ% h¡\Ð2Ô3ØÐÐr;   c                óÜ   • [         R                  S5        / n[        5       nU SSS2    H>  nSUR                  5       0nUS   S-   US'   US==   S-  ss'   UR	                  U5        M@     U$ )a  
If receiveds are not parsed, makes a new structure with raw
field. It's useful to have the same structure of receiveds
parsed.

Args:
    receiveds (list): list of raw receiveds headers

Returns:
    a list of not parsed receiveds headers with first hop in first position
z'Receiveds for this email are not parsedNéÿÿÿÿrÔ   Úhopr   )r3   r4   r   r-   r2   )rÙ   rb   ÚcounterrÉ   Újs        r   r×   r×   @  sr   € ô ‡I�IÐ7Ô8à€FÜ‹i€Gà‘t˜�tŒ_ˆØ�A—G‘G“IÐˆØ˜5‘> AÑ%ˆˆ%‰Ø�‹˜!Ñ‹Ø�‰�aÖñ	 ð €Mr;   c                ó~  • [         R                  S5        / n[        5       nU SSS2    GH6  nUR                  5        VVs0 s H  u  pEU(       d  M  XER	                  5       _M      nnnUS   S-   US'   UR                  S5      (       aM  US   R                  S5      S   US'   [        R                  " SS	US   5      US'    [        US   5      u  US
'   n[        U5      nUR                  S
5      n	U(       aC  U	(       a<  XS   S-
     R                  S
5      n
U
(       a  Xš-
  R                  5       US'   OSUS'   OSUS'   UR                  U5        US==   S-  ss'   GM9     U H1  nUR                  S
5      (       d  M  US
   R                  5       US
'   M3     U$ s  snnf ! [        [        4 a    SUS
'    Näf = f)zÍ
Given a list of receiveds hop, adds metadata and reformat
field values

Args:
    receiveds (list): list of receiveds hops already formatted

Returns:
    list of receiveds reformated and with new fields
z#Receiveds for this email are parsedNré   rê   r   r±   Ú;z^\s*(?:\([^)]*\)\s*)+r#   ræ   Údelayr   )r3   r4   r   Úitemsr-   r”   r¼   r¿   rÕ   rç   Ú	TypeErrorrk   r5   Útotal_secondsr2   Ú	isoformat)rÙ   rb   rë   rÉ   ÚkÚvrì   r   ÚsizeÚnowÚbefores              r   rØ   rØ   Z  s°  € ô ‡I�IÐ3Ô4à€FÜ‹i€Gà‘t˜�t�_ˆà&'§g¡g¤iÔ5¢i™d˜a´1‹\ˆQ—‘“	Š\¡iˆÑ5ð ˜5‘> AÑ%ˆˆ%‰ð �5‰5��=‰=ð ˜&™	Ÿ™¨Ó,¨RÑ0ˆAˆf‰Iô ŸšÐ7¸¸Q¸v¹YÓGˆAˆf‰Ið%Ü#4°Q°v±YÓ#?Ñ ��*‘˜qô
 �6‹{ˆØ�e‰e�JÓˆæ–CØ E™N¨QÑ.Ñ/×3Ñ3°JÓ?ˆFÞØ!™l×9Ñ9Ó;��'’
à��'’
àˆAˆg‰Jð 	�‰�aÔð 	�‹˜!ÑŽñK óN ˆØ�5‰5�×ÓØ˜j™M×3Ñ3Ó5ˆAˆj‹Mñ ð €MùóQ 6øô œzÐ*ó %Ø $��*“ð%ús   ÁFÁFÃF$Æ$F<Æ;F<c                óö   • [        5       nX-    HF  n UR                  US   R                  S5      S   R                  5       R	                  5       5        MH     [        U5      $ ! [
        [        4 a     Mh  f = f)Nr   Ú@ré   )ÚsetÚaddr¼   r½   r-   ÚKeyErrorÚ
IndexErrorrÁ   )ÚtoÚreply_toÚdomainsrÉ   s       r   Úget_to_domainsr  —  sn   € Ü‹e€GØŒ]ˆð	Ø�K‰K˜˜!™Ÿ
™
 3›¨Ñ+×1Ñ1Ó3×9Ñ9Ó;Ö<ñ ô �‹=Ðøô œ*Ð%ó 	Úð	ús   “AA$Á$A8Á7A8c                ó  • U R                  U5      n[        R                  SU< SU< 35        U(       a?  U Vs/ s H  n[        U5      PM     nn[	        U5      S:X  a  US   R                  5       $ U$ [        5       $ s  snf )a  
Gets an email.message.Message and a header name and returns
the mail header decoded with the correct charset.

Args:
    message (email.message.Message): email message object
    name (string): header to get

Returns:
    str if there is an header
    list if there are more than one
zGetting header z: r   r   )Úget_allr3   r4   r(   r5   r-   r*   )r¯   rG   ÚheadersrÉ   s       r   Ú
get_headerr  ¢  sx   € ð �o‰o˜dÓ#€GÜ‡I�I� ™x r¨'©Ð5Ô6ÞÙ29Ó:²'¨QÔ% aÖ(±'ˆÐ:Üˆw‹<˜1Óà˜1‘:×#Ñ#Ó%Ð%àˆÜ‹5€Lùò ;s   ºA?c                ón  • U(       aS  [         R                  S5        U R                  5        Vs1 s H  o"R                  5       iM     nn[        [
        -  U-  nO"[         R                  S5        [        [
        -  n[         R                  SR                  SR                  U5      5      5        U$ s  snf )zé
Given an email.message.Message, return a set with all email parts to get

Args:
    message (email.message.Message): email message object
    complete (bool): if True returns all email headers

Returns:
    set with all email parts
zGet all headerszGet only mains headerszAll parts to get: {}z, )r3   r4   rÂ   r½   r   r   ÚformatÚjoin)r¯   ÚcompleterÉ   Úall_headers_keysÚ	all_partss        r   Úget_mail_keysr  ¼  s†   € ö Ü�	‰	Ð#Ô$Ø/6¯|©|¬~Ó>ª~¨!ŸG™GžI©~ÐÐ>Ü%¬Ñ4Ð7GÑG‰	ä�	‰	Ð*Ô+Ü%¬Ñ4ˆ	ä‡I�IÐ$×+Ñ+¨D¯I©I°iÓ,@ÓAÔBØÐùò ?s   ¯B2c                óp   •  [        U 5        g ! [         a    [        U R                  S5      5         g f = f)NrW   )ÚprintÚUnicodeEncodeErrorr)   )r|   s    r   Ú
safe_printr  Ô  s.   € ð$Üˆd�øÜó $Üˆd�k‰k˜'Ó"Ö#ð$ús   ‚ Ž$5´5c                ó�   • [        U 5      u  pp4[        SU 35        [        SU 35        [        SU 35        [        SU 35        g )Nzmd5:	zsha1:	zsha256:	zsha512:	)r~   r  )r|   rv   ry   rz   r{   s        r   Úprint_mail_fingerprintsr  Û  sL   € Ü ,¨TÓ 2Ñ€CˆvÜ	ˆF�3�%ˆ.ÔÜ	ˆG�D�6Ð
ÔÜ	ˆI�f�XÐ
ÔÜ	ˆI�f�XÐ
Õr;   c           	     ó  • U(       aY  U  HS  nUR                  S5      S:X  a  [        R                  " US   5      nOUS   n[        U5      u  US'   US'   US'   US'   MU     U  H"  n[	        [
        R                  " USS	S
95        M$     g )NÚcontent_transfer_encodingÚbase64Úpayloadrv   ry   rz   r{   Fr    )Úensure_asciiÚindent)r”   r  Ú	b64decoder~   r  ÚjsonÚdumps)ÚattachmentsÚ	flag_hashrÉ   r  s       r   Úprint_attachmentsr  ã  s‚   € ÞÛˆAØ�u‰uÐ0Ó1°XÓ=Ü ×*Ò*¨1¨Y©<Ó8‘à˜I™,�ä<HÈÓ<QÑ9ˆAˆe‰H�a˜‘i  8¡¨a°«kñ ó ˆÜ”4—:’:˜a¨e¸AÑ>Ö?ò r;   c                ó@   • U  H  n[        US   US   UUS   S9  M     g )NÚbinaryr  Úfilename)r!  r  r‡   r"  )Úwrite_sample)r  Ú	base_pathÚas      r   Úwrite_attachmentsr&  ñ  s,   € ÛˆÜØ�X‘;Ø�i‘LØØ�z‘]ô		
ò r;   c                óÊ  • [         R                  R                  U5      (       d  [         R                  " U5        [         R                  R	                  X#5      nU (       a;  [        US5       nUR                  [        R                  " U5      5        SSS5        g[        US5       nUR                  U5        SSS5        g! , (       d  f       g= f! , (       d  f       g= f)a  
This function writes a sample on file system.

Args:
    binary (bool): True if it's a binary file
    payload: payload of sample, in base64 if it's a binary
    path (string): path of file
    filename (string): name of file
    hash_ (string): file hash
rŽ   NÚw)	r„   r‡   ÚexistsÚmakedirsr	  rf   r•   r  r  )r!  r  r‡   r"  Úsampler�   s         r   r#  r#  û  s—   € ô �7‰7�>‰>˜$×ÑÜ
�Š�DÔÜ�W‰W�\‰\˜$Ó)€FæÜ�&˜$Ô 1Ø�G‰G”F×$Ò$ WÓ-Ô.÷  Ðô �&˜#Ô !Ø�G‰G�GÔ÷ Ð÷  Õú÷ Õús   Á-&CÂ(CÃ
CÃ
C"c                ól   ^• [         R                  mSR                  U4S j[        U 5       5       5      $ )z™Generate a random string of fixed length

Keyword Arguments:
    string_length {int} -- String length (default: {10})

Returns:
    str -- Random string
r#   c              3  óP   >#   • U  H  n[         R                  " T5      v •  M     g 7fr   )ÚrandomÚchoice)r   r   Úletterss     €r   r   Ú random_string.<locals>.<genexpr>  s   øé € ÐHÒ3G¨a”6—=’= ×)Ð)Ò3Gùs   ƒ#&)ÚstringÚascii_lowercaser	  Úrange)Ústring_lengthr0  s    @r   Úrandom_stringr6    s*   ø€ ô ×$Ñ$€GØ�7‰7ÔH´5¸Ô3GÓHÓHÐHr;   )r6   z str | email.header.Header | NoneÚreturnzlist[tuple[str, str]])ÚWARNINGN)rW   r_   )T)é
   )DÚ__doc__Ú
__future__r   r  rá   r%   Úemail.headerÚemail.utilsrS   ru   r  r=   r„   r.  r¿   r2  r£   rA   r‚   Úcollectionsr   r   Úemail.errorsr   r   Úunicodedatar	   Úmailparser.constr
   r   r   r   r   r   r   Úmailparser.exceptionsr   r   r>   r“   r3   Úcompiler/   r:   rJ   rU   r]   r(   rh   rq   r~   rˆ   rž   r    rÐ   rÜ   rç   r×   rØ   r  r  r  r  r  r  r&  r#  r6  r   r;   r   Ú<module>rD     s6  ðñõ  #ã Û Û Û Û Û Û Û Û Û 	Û Û 	Û Û Û 
Û ß +Ý )Ý &Ý !÷÷ ñ ÷ Tà×Ò˜Ó!€ð( —J’JðóÐ ðPØ0ðPàôPôfò:ð 
ó.ó 
ð.ò<ò8	:òò$-òNò )òX(8òVUòp+(ò\ò$ò4:ðz  2ô òô4ò0$ò ò@ò
òõ.
Ir;   