a
    aiiQ                     @  sH  U d dl mZ d dlmZ d dlZd dlZd dlZd dlZ	d dl
Z
d dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dl m!Z! d dl"m#Z# d dl$Z$d dl%m&Z& d dl%m'Z' e	j(r"d dl)Z*e+dej,dd G dd de-Z.dDdddddddZ/dEddddddZ0dFdddd d!d"Z1dGd#dd$d%d&d'Z2dd(d)d*d+Z3G d,d- d-Z4G d.d/ d/e5Z6G d0d1 d1Z7G d2d3 d3Z8G d4d5 d5Z9G d6d7 d7e9Z:G d8d9 d9e9Z;e$< Z=d:e>d;< e=j?d<d=d>Z@d?e>d@< dddAdBdCZAdS )H    )annotationsN)contextmanager)charset)policy)encode_base64)Header)MIMEBase)MIMEMultipart)MIMEText)
formataddr)
formatdate)
make_msgid)	parseaddr)
guess_type)TracebackType)current_app)Flaskutf-8c                      s8   e Zd Zdddd fddZdd fdd	Z  ZS )
FlaskMailUnicodeDecodeErrort.AnyNone)objargsreturnc                   s   || _ t j|  d S N)r   super__init__)selfr   r   	__class__ M/var/www/html/SiteWeb/venv/lib/python3.9/site-packages/flask_mail/__init__.pyr   $   s    z$FlaskMailUnicodeDecodeError.__init__strr   c                   s(   t   }| d| jdt| j dS )Nz. You passed in z ())r   __str__r   type)r   originalr   r    r!   r%   (   s    
z#FlaskMailUnicodeDecodeError.__str__)__name__
__module____qualname__r   r%   __classcell__r    r    r   r!   r   #   s   r   strictr   r"   )sencodingerrorsr   c              
     s   t | tr| S z$t | tr(t|  }nt| }W n^ ty } zFt | ts`t| g|jR  |d fdd| jD }W Y d}~n
d}~0 0 |S )zz
    Similar to smart_text, except that lazy instances are resolved to
    strings, rather than kept as lazy objects.
     c                   s   g | ]}t | qS r    )
force_text).0argr.   r/   r    r!   
<listcomp>>       zforce_text.<locals>.<listcomp>N)
isinstancer"   bytesUnicodeDecodeError	Exceptionr   r   join)r-   r.   r/   outer    r4   r!   r1   -   s    


2r1   )subjectr.   r   c                 C  sZ   z|  d W nF tyT   zt| |  } W n  tyN   t| d  } Y n0 Y n0 | S )Nasciir   )encodeUnicodeEncodeErrorr   )r>   r.   r    r    r!   sanitize_subjectC   s    rB   str | tuple[str, str])addrr.   r   c                 C  s   t | trtt| } | \}} zt|| }W n  tyP   t|d }Y n0 z| d W nf ty   d| v r| dd\}}tt||}|dd}d	||g} nt| | } Y n0 t
|| fS )Nr   r?   @   idna)r7   r"   r   r1   r   r@   rA   splitdecoder;   r   )rD   r.   nmZ	localpartdomainr    r    r!   sanitize_addressO   s"    
rL   z!c.Iterable[str | tuple[str, str]]z	list[str])	addressesr.   r   c                   s    fdd| D S )Nc                   s   g | ]}t | qS r    )rL   )r2   r=   r.   r    r!   r5   k   r6   z&sanitize_addresses.<locals>.<listcomp>r    )rM   r.   r    rN   r!   sanitize_addressesh   s    rO   bool)liner   c                 C  s   d| v pd| v S )z,Used by has_bad_header to check for \r or \n
r    )rQ   r    r    r!   _has_newlinen   s    rT   c                   @  sv   e Zd ZdZdddddZddd	d
ZdddddddZddddZdddddddZddddddZ	dS )
ConnectionzHandles connection to host.Mailr   )mailr   c                 C  s   || _ d | _d| _d S Nr   )rW   host
num_emails)r   rW   r    r    r!   r   v   s    zConnection.__init__zte.Selfr#   c                 C  s$   | j jrd | _n
|  | _d| _| S rX   )rW   suppressrY   configure_hostrZ   r   r    r    r!   	__enter__{   s
    
zConnection.__enter__ztype[BaseException]BaseExceptionr   )exc_type	exc_valuetbr   c                 C  s   | j d ur| j   d S r   )rY   quit)r   r`   ra   rb   r    r    r!   __exit__   s    
zConnection.__exit__zsmtplib.SMTP | smtplib.SMTP_SSLc                 C  s|   | j jrt| j j| j j}nt| j j| j j}|t| j j	 | j j
rT|  | j jrx| j jrx|| j j| j j |S r   )rW   use_sslsmtplibZSMTP_SSLserverportSMTPset_debuglevelintdebuguse_tlsstarttlsusernamepasswordlogin)r   rY   r    r    r!   r\      s    zConnection.configure_hostNMessagestr | tuple[str, str] | None)messageenvelope_fromr   c                 C  s   |j sJ d|jsJ d| r(t|jdu r<t |_| jdurv| jt|pV|jt	t
|j | |j|j t }tj||d |  jd7  _| j| jjkrd| _| jr| j  |  | _dS )zVerifies and sends message.

        :param message: Message instance.
        :param envelope_from: Email address to be used in MAIL FROM command.
        zNo recipients have been addedzRThe message does not specify a sender and a default sender has not been configuredN)rt   rF   r   )send_tosenderhas_bad_headersBadHeaderErrordatetimerY   ZsendmailrL   listrO   as_bytesmail_optionsrcpt_optionsr   Z_get_current_objectemail_dispatchedsendrZ   rW   
max_emailsrc   r\   )r   rt   ru   appr    r    r!   r      s0    



zConnection.sendr   r   kwargsr   c                 O  s   |  t|i | dS ztShortcut for send(msg).

        Takes same arguments as Message constructor.

        :versionadded: 0.3.5
        Nr   rr   r   r   r   r    r    r!   send_message   s    zConnection.send_message)N)
r(   r)   r*   __doc__r   r^   rd   r\   r   r   r    r    r    r!   rU   s   s   	 (rU   c                   @  s   e Zd ZdS )ry   N)r(   r)   r*   r    r    r    r!   ry      s   ry   c                   @  s(   e Zd ZdZd	ddddddddZdS )

Attachmenta?  Encapsulates file attachment information.

    :param filename: filename of attachment
    :param content_type: file mimetype
    :param data: the raw file data
    :param disposition: content-disposition (if any)

    .. versionchanged:: 0.10.0
        The `data` argument is required.

    .. versionadded: 0.3.5
    N
str | Nonestr | bytes | Nonedict[str, str] | None)filenamecontent_typedatadispositionheadersc                 C  sz   |d u rt d|| _|d u r2|d ur2t|d }|d u rNt|trJd}nd}|| _|| _|p`d| _|d u rpi }|| _d S )Nz The 'data' argument is required.r   z
text/plainzapplication/octet-stream
attachment)	
ValueErrorr   r   r7   r"   r   r   r   r   r   r   r   r   r   r   r    r    r!   r      s    

zAttachment.__init__)NNNNN)r(   r)   r*   r   r   r    r    r    r!   r      s        r   c                   @  s&  e Zd ZdZd;ddddddddd	dd
dddddddZeddddZeddddZejdddddZd<ddddddZ	dddd Z
ddd!d"Zd#dd$d%Zddd&d'Zd#dd(d)Zd*dd+d,Zd*dd-d.Zd/dd0d1d2Zd3dd4d5d6Zd=ddd7dddd8d9d:ZdS )>rr   a;  Encapsulates an email message.

    :param subject: email subject header
    :param recipients: list of email addresses
    :param body: plain text message
    :param html: HTML message
    :param alts: A dict or an iterable to go through dict() that contains multipart
                 alternatives
    :param sender: email sender address, or **MAIL_DEFAULT_SENDER** by default
    :param cc: CC list
    :param bcc: BCC list
    :param attachments: list of Attachment instances
    :param reply_to: reply-to address
    :param date: send date
    :param charset: message character set
    :param extra_headers: A dictionary of additional headers for the message
    :param mail_options: A list of ESMTP options to be used in MAIL FROM command
    :param rcpt_options:  A list of ESMTP options to be used in RCPT commands
     Nr"   z"list[str | tuple[str, str]] | Noner   z3dict[str, str] | c.Iterable[tuple[str, str]] | Noners   zlist[Attachment] | Nonezfloat | Noner   zlist[str] | None)r>   
recipientsbodyhtmlaltsrw   ccbccattachmentsreply_torz   r   extra_headersr~   r   c                 C  s   |pt jd j}t|tr2|d  d|d  d}|p8g | _|| _|| _|
| _|pTg | _	|p^g | _
|| _t|ppi | _|| _|| _t | _|| _|| _|pg | _|pg | _|	pg | _d S )NrW   r    <rF   >)r   
extensionsdefault_senderr7   tupler   r>   rw   r   r   r   r   dictr   r   rz   r   msgIdr   r   r~   r   r   )r   r>   r   r   r   r   rw   r   r   r   r   rz   r   r   r~   r   r    r    r!   r     s&    





zMessage.__init__zset[str | tuple[str, str]]r#   c                 C  s2   t | j}| jr|| j | jr.|| j |S r   )setr   r   updater   )r   r<   r    r    r!   rv   =  s    
zMessage.send_toc                 C  s   | j dS Nr   )r   getr]   r    r    r!   r   I  s    zMessage.htmlr   )valuer   c                 C  s&   |d u r| j dd  n
|| j d< d S r   )r   pop)r   r   r    r    r!   r   M  s    plainr
   )textsubtyper   c                 C  s   | j pd}t|||dS )zCreates a MIMEText object with the given subtype (default: 'plain')
        If the text is unicode, the utf-8 charset is used.
        r   )_subtype_charset)r   r
   )r   r   r   r   r    r    r!   	_mimetextT  s    
zMessage._mimetextr   c              
   C  s  t jd j}| jpd}| jpg }t|dkr@| js@| | j}n~t|dkrl| jslt	 }|
| | j nRt	 }t	d}|
| | jd | j D ]\}}|
| || q|
| | jrtt| j||d< t| j||d< dttt| j||d	< t| jd
d|d< | j|d< | jrHdttt| j||d< | jr`t| j||d< | jr| j D ]\}}	|	||< qrtdtj}
|D ]}t|j !d }|"|j# t$| |j%durV|j%}|rt&'d|j%}|(dd)d}|
*d|+ }z|(d W n, t,yB   |j-d|j.dd|fd Y n0 |j-d|j.|d |j/ D ]\}}|-|| q`|
| qt0j1|_0|S )zCreates the emailrW   r   r   alternativer   SubjectFromz, ToT)	localtimeDatez
Message-IDCczReply-Toz[\s]+/NZNFKDr?   ignorer0   zContent-DispositionUTF8r   )r   )2r   r   ascii_attachmentsr   r   lenr   r   r   r	   attachitemsr>   rB   r1   rL   rw   r;   r|   r   rO   r   r   rz   r   r   r   r   recompileUNICODEr   r   rH   set_payloadr   r   r   unicodedata	normalizer@   rI   substriprA   
add_headerr   r   r   ri   )r   r   r.   r   msgr   mimetypecontentkvZSPACESr   fr   keyr   r    r    r!   _message[  sl    



zMessage._messagec                 C  s   |    S r   )r   	as_stringr]   r    r    r!   r     s    zMessage.as_stringr8   c                 C  s   |    S r   )r   r}   r]   r    r    r!   r}     s    zMessage.as_bytesc                 C  s   |   S r   )r   r]   r    r    r!   r%     s    zMessage.__str__c                 C  s   |   S r   )r}   r]   r    r    r!   	__bytes__  s    zMessage.__bytes__rP   c                 C  s   | j g| j}| jr || j |D ]4}t|trJ|d  d|d  d}t|r$ dS q$| jrt| jrt| j	dD ]P\}}|s dS |dkr|d dvr dS t|r dS t
| dkrz dS qzdS )	zChecks for bad headers i.e. newlines in subject, sender or recipients.
        RFC5322: Allows multiline CRLF with trailing whitespace (FWS) in headers
        r   r   rF   r   Tz
z	 F)rw   r   r   appendr7   r   rT   r>   	enumeraterH   r   r   )r   r   headerZlinenumrQ   r    r    r!   rx     s(    

zMessage.has_bad_headersc                 C  s   t jdtdd |  S )Nzs'is_bad_headers' is renamed to 'has_bad_headers'. The old name is deprecated and will be removed in Flask-Mail 1.0.   
stacklevel)warningswarnDeprecationWarningrx   r]   r    r    r!   is_bad_headers  s    zMessage.is_bad_headersrU   )
connectionr   c                 C  s   | |  dS )zVerifies and sends the message.N)r   )r   r   r    r    r!   r     s    zMessage.sendrC   )	recipientr   c                 C  s   | j | dS )zfAdds another recipient to the message.

        :param recipient: email address of recipient.
        N)r   r   )r   r   r    r    r!   add_recipient  s    zMessage.add_recipientr   )r   r   r   r   r   r   c                 C  s   | j t||||| dS )zAdds an attachment to the message.

        :param filename: filename of attachment
        :param content_type: file mimetype
        :param data: the raw file data
        :param disposition: content-disposition (if any)
        N)r   r   r   r   r    r    r!   r     s    zMessage.attach)r   NNNNNNNNNNNNNN)r   )NNNNN)r(   r)   r*   r   r   propertyrv   r   setterr   r   r   r}   r%   r   rx   r   r   r   r   r    r    r    r!   rr      sN                  ,(Q	
     rr   c                   @  sN   e Zd ZeddddZddddd	Zd
d
ddddZddddZdS )
_MailMixinzc.Iterator[list[Message]]r#   c                 #  sN   g  dddd fdd}t |  V  W d   n1 s@0    Y  dS )a3  Records all messages. Use in unit tests for example::

            with mail.record_messages() as outbox:
                response = app.test_client.get("/email-sending-view/")
                assert len(outbox) == 1
                assert outbox[0].subject == "testing"

        :versionadded: 0.4
        r   rr   r   )r   rt   r   c                   s     | d S r   )r   )r   rt   Zoutboxr    r!   record  s    z*_MailMixin.record_messages.<locals>.recordN)r   Zconnected_to)r   r   r    r   r!   record_messages  s    z_MailMixin.record_messagesrr   r   )rt   r   c                 C  s6   |   }|| W d   n1 s(0    Y  dS )zSends a single message instance. If TESTING is True the message will
        not actually be sent.

        :param message: a Message instance.
        N)connectr   )r   rt   r   r    r    r!   r     s    
z_MailMixin.sendr   r   c                 O  s   |  t|i | dS r   r   r   r    r    r!   r     s    z_MailMixin.send_messagerU   c              
   C  sT   t | ddpt}zt|jd W S  tyN } ztd|W Y d}~n
d}~0 0 dS )z$Opens a connection to the mail host.r   NrW   z:The current application was not configured with Flask-Mail)getattrr   rU   r   KeyErrorRuntimeError)r   r   errr    r    r!   r   (  s    z_MailMixin.connectN)r(   r)   r*   r   r   r   r   r   r    r    r    r!   r      s
   

r   c                   @  s.   e Zd ZddddddddddddddZd	S )
_Mailr"   r   z
int | NonerP   rk   rg   ro   rp   rh   rm   re   r   rl   r   r[   r   c                 C  sF   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	|| _
d S r   r   )r   rg   ro   rp   rh   rm   re   r   rl   r   r[   r   r    r    r!   r   5  s    z_Mail.__init__N)r(   r)   r*   r   r    r    r    r!   r   4  s   r   c                   @  sX   e Zd ZdZddddddZdd	d
dddddZdddddZdddddZdS )rV   zManages email messaging.NzFlask | Noner   )r   r   c                 C  s&   || _ |d ur| || _nd | _d S r   )r   init_appstate)r   r   r    r    r!   r   S  s    zMail.__init__Fzdict[str, t.Any]z
bool | intrP   r   )configrl   testingr   c                 C  sp   t |dd|d|d|dd|dd|d	d|d
t|d||d|d||ddS )NZMAIL_SERVERz	127.0.0.1ZMAIL_USERNAMEZMAIL_PASSWORDZ	MAIL_PORT   ZMAIL_USE_TLSFZMAIL_USE_SSLZMAIL_DEFAULT_SENDERZ
MAIL_DEBUGZMAIL_MAX_EMAILSZMAIL_SUPPRESS_SENDZMAIL_ASCII_ATTACHMENTS)r   r   rk   )r   r   rl   r   r    r    r!   	init_mail[  s    





zMail.init_mailr   c                 C  s0   |  |j|j|j}t|di |_||jd< |S )zInitializes your mail settings from the application settings.

        You can use this if you want to set up your Mail instance
        at configuration time.
        r   rW   )r   r   rl   r   r   r   )r   r   r   r    r    r!   r   l  s    
zMail.init_appr"   r   namer   c                 C  s   t | j|d S r   )r   r   )r   r   r    r    r!   __getattr__y  s    zMail.__getattr__)N)FF)r(   r)   r*   r   r   r   r   r   r    r    r    r!   rV   P  s   	 rV   zblinker.Namespacesignalszemail-dispatchedz
Signal sent when an email is dispatched. This signal will also be sent
in testing mode, even though the email will not actually be sent.
)doczblinker.NamedSignalr   r   c                 C  s8   | dkr,dd l }tjdtdd |jdS t| d S )N__version__r   zThe '__version__' attribute is deprecated and will be removed in Flask-Mail 1.0. Use feature detection or 'importlib.metadata.version("flask-mail")' instead.r   r   z
flask-mail)importlib.metadatar   r   r   metadataversionAttributeError)r   	importlibr    r    r!   r     s    r   )r   r,   )r   )r   )r   )B
__future__r   collections.abcabccr   rf   r{   typingtr   r   
contextlibr   emailr   r   email.encodersr   Zemail.headerr   Zemail.mime.baser   Zemail.mime.multipartr	   Zemail.mime.textr
   email.utilsr   r   r   r   	mimetypesr   typesr   ZblinkerZflaskr   r   TYPE_CHECKINGZtyping_extensionsteadd_charsetSHORTESTr9   r   r1   rB   rL   rO   rT   rU   r:   ry   r   rr   r   r   rV   	Namespacer   __annotations__signalr   r   r    r    r    r!   <module>   sb   
 [.  4-	