o
    JfiQ                     @  s  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(rd dl)Z*e+dej,dd G dd de-Z.dGdHddZ/dIdJd d!Z0dIdKd$d%Z1	dIdLd)d*Z2dMd-d.Z3G d/d0 d0Z4G d1d2 d2e5Z6G d3d4 d4Z7G d5d6 d6Z8G d7d8 d8Z9G d9d: d:e9Z:G d;d< d<e9Z;e$< Z=d=e>d>< e=j?d?d@dAZ@dBe>dC< dNdEdFZAdS )O    )annotationsN)contextmanager)charset)policy)encode_base64)Header)MIMEBase)MIMEMultipart)MIMEText)
formataddr)
formatdate)
make_msgid)	parseaddr)
guess_type)TracebackType)current_app)Flaskutf-8c                      s,   e Zd Zd fddZd fd	d
Z  ZS )FlaskMailUnicodeDecodeErrorobjt.AnyargsreturnNonec                   s   || _ t j|  d S N)r   super__init__)selfr   r   	__class__ L/home/ubuntu/webapp/venv/lib/python3.10/site-packages/flask_mail/__init__.pyr   $   s   z$FlaskMailUnicodeDecodeError.__init__strc                   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__)r   r   r   r   r   r   r   r"   )__name__
__module____qualname__r   r$   __classcell__r    r    r   r!   r   #   s    r   strictsr   encodingr"   errorsr   c              
     s   t | tr| S zt | trt|  }W |S t| }W |S  tyL } z$t | ts3t| g|jR  |d fdd| jD }W Y d}~|S d}~ww )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>>   s    zforce_text.<locals>.<listcomp>N)
isinstancer"   bytesUnicodeDecodeError	Exceptionr   r   join)r-   r.   r/   outer    r4   r!   r1   -   s   

	

&r1   subjectc                 C  s\   z|  d W | S  ty-   zt| |  } W Y | S  ty,   t| d  } Y Y | S w w )Nasciir   )encodeUnicodeEncodeErrorr   )r=   r.   r    r    r!   sanitize_subjectC   s   rA   addrstr | tuple[str, str]c                 C  s   t | trtt| } | \}} z	t|| }W n ty(   t|d }Y nw z| d W n3 tyc   d| v rZ| dd\}}tt||}|dd}d	||g} nt| | } Y nw t
|| fS )Nr   r>   @   idna)r6   r"   r   r1   r   r?   r@   splitdecoder:   r   )rB   r.   nm	localpartdomainr    r    r!   sanitize_addressO   s(   
	rL   	addresses!c.Iterable[str | tuple[str, str]]	list[str]c                   s    fdd| D S )Nc                   s   g | ]}t | qS r    )rL   )r2   r<   r.   r    r!   r5   k   s    z&sanitize_addresses.<locals>.<listcomp>r    )rM   r.   r    rP   r!   sanitize_addressesh   s   rQ   lineboolc                 C  s   d| v pd| v S )z,Used by has_bad_header to check for \r or \n
r    )rR   r    r    r!   _has_newlinen   s   rV   c                   @  sP   e Zd ZdZd"ddZd#d	d
Zd$ddZd%ddZ	d&d'ddZd(d d!Z	dS ))
ConnectionzHandles connection to host.mailMailr   r   c                 C  s   || _ d | _d| _d S Nr   )rX   host
num_emails)r   rX   r    r    r!   r   v   s   
zConnection.__init__te.Selfc                 C  s$   | j jrd | _n|  | _d| _| S rZ   )rX   suppressr[   configure_hostr\   r   r    r    r!   	__enter__{   s
   
zConnection.__enter__exc_typetype[BaseException]	exc_valueBaseExceptiontbr   c                 C  s   | j d ur| j   d S d S r   )r[   quit)r   rb   rd   rf   r    r    r!   __exit__   s   
zConnection.__exit__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
r*|  | j jr<| j jr<|| j j| j j |S r   )rX   use_sslsmtplibSMTP_SSLserverportSMTPset_debuglevelintdebuguse_tlsstarttlsusernamepasswordlogin)r   r[   r    r    r!   r_      s   zConnection.configure_hostNmessageMessageenvelope_fromstr | tuple[str, str] | Nonec                 C  s   |j sJ d|jsJ d| rt|jdu rt |_| jdur;| jt|p+|jt	t
|j | |j|j t }tj||d |  jd7  _| j| jjkrfd| _| jrh| j  |  | _dS dS 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)rx   rE   r   )send_tosenderhas_bad_headersBadHeaderErrordatetimer[   sendmailrL   listrQ   as_bytesmail_optionsrcpt_optionsr   _get_current_objectemail_dispatchedsendr\   rX   
max_emailsrg   r_   )r   rx   rz   appr    r    r!   r      s4   



zConnection.sendr   r   kwargsc                 O     |  t|i | dS ztShortcut for send(msg).

        Takes same arguments as Message constructor.

        :versionadded: 0.3.5
        Nr   ry   r   r   r   r    r    r!   send_message   s   zConnection.send_message)rX   rY   r   r   )r   r]   )rb   rc   rd   re   rf   r   r   r   )r   ri   r   )rx   ry   rz   r{   r   r   r   r   r   r   r   r   )
r(   r)   r*   __doc__r   ra   rh   r_   r   r   r    r    r    r!   rW   s   s    


	
(rW   c                   @  s   e Zd ZdS )r   N)r(   r)   r*   r    r    r    r!   r      s    r   c                   @  s&   e Zd ZdZ					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filename
str | Nonecontent_typedatastr | bytes | Nonedispositionheadersdict[str, str] | Nonec                 C  sz   |d u rt d|| _|d u r|d urt|d }|d u r't|tr%d}nd}|| _|| _|p0d| _|d u r8i }|| _d S )Nz The 'data' argument is required.r   z
text/plainzapplication/octet-stream
attachment)	
ValueErrorr   r   r6   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   )r(   r)   r*   r   r   r    r    r    r!   r      s    r   c                   @  s   e Zd ZdZ															dNdOddZedPd d!ZedQd"d#ZejdRd&d#ZdSdTd+d,Z	dUd.d/Z
dVd0d1ZdWd3d4ZdVd5d6ZdWd7d8ZdXd:d;ZdXd<d=ZdYd@dAZdZdDdEZ					d[d\dLdMZdS )]ry   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=   r"   
recipients"list[str | tuple[str, str]] | Nonebodyr   htmlalts3dict[str, str] | c.Iterable[tuple[str, str]] | Noner}   r{   ccbccattachmentslist[Attachment] | Nonereply_tor   float | Noner   extra_headersr   r   list[str] | Noner   c                 C  s   |pt jd j}t|tr|d  d|d  d}|pg | _|| _|| _|
| _|p*g | _	|p/g | _
|| _t|p8i | _|| _|| _t | _|| _|| _|pNg | _|pSg | _|	pXg | _d S )NrX   r    <rE   >)r   
extensionsdefault_senderr6   tupler   r=   r}   r   r   r   r   dictr   r   r   r   msgIdr   r   r   r   r   )r   r=   r   r   r   r   r}   r   r   r   r   r   r   r   r   r   r    r    r!   r     s&   





zMessage.__init__r   set[str | tuple[str, str]]c                 C  s2   t | j}| jr|| j | jr|| j |S r   )setr   r   updater   )r   r;   r    r    r!   r|   =  s   
zMessage.send_toc                 C  s   | j dS Nr   )r   getr`   r    r    r!   r   I  s   zMessage.htmlvaluer   c                 C  s(   |d u r| j dd  d S || j d< d S r   )r   pop)r   r   r    r    r!   r   M  s   plain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r6| js6t	 }|
| | j n)t	 }t	d}|
| | jd | j D ]\}}|
| || qL|
| | jrltt| j||d< t| j||d< dttt| j||d	< t| jd
d|d< | j|d< | jrdttt| j||d< | jrt| j||d< | jr| j D ]\}}	|	||< qtdtj}
|D ]t}t|j !d }|"|j# t$| |j%dur&|j%}|rt&'d|j%}|(dd)d}|
*d|+ }z|(d W n t,y   |j-d|j.dd|fd Y n
w |j-d|j.|d |j/ D ]\}}|-|| q+|
| qt0j1|_0|S )zCreates the emailrX   r   r   alternativer   SubjectFromz, ToT)	localtimeDatez
Message-IDCczReply-Toz[\s]+/NNFKDr>   ignorer0   zContent-DispositionUTF8r   )r   )2r   r   ascii_attachmentsr   r   lenr   r   r   r	   attachitemsr=   rA   r1   rL   r}   r:   r   r   rQ   r   r   r   r   r   r   r   recompileUNICODEr   r   rG   set_payloadr   r   r   unicodedata	normalizer?   rH   substripr@   
add_headerr   r   r   ro   )r   r   r.   r   msgr   mimetypecontentkvSPACESr   fr   keyr   r    r    r!   _message[  sn   





zMessage._messagec                 C     |    S r   )r   	as_stringr`   r    r    r!   r        zMessage.as_stringr7   c                 C  r   r   )r   r   r`   r    r    r!   r     r   zMessage.as_bytesc                 C     |   S r   )r   r`   r    r    r!   r$        zMessage.__str__c                 C  r   r   )r   r`   r    r    r!   	__bytes__  r   zMessage.__bytes__rS   c                 C  s   | j g| j}| jr|| j |D ]}t|tr%|d  d|d  d}t|r, dS q| jrft| jrft| j	dD ](\}}|sF dS |dkrS|d dvrS dS t|rZ dS t
| dkre dS q=d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   rE   r   Tz
z	 F)r}   r   r   appendr6   r   rV   r=   	enumeraterG   r   r   )r   r   headerlinenumrR   r    r    r!   r~     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DeprecationWarningr~   r`   r    r    r!   is_bad_headers  s   zMessage.is_bad_headers
connectionrW   c                 C  s   | |  dS )zVerifies and sends the message.N)r   )r   r   r    r    r!   r     s   zMessage.send	recipientrC   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   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=   r"   r   r   r   r   r   r   r   r   r}   r{   r   r   r   r   r   r   r   r{   r   r   r   r   r   r   r   r   r   r   )r   r   )r   r   )r   r   r   r   )r   )r   r   r   r"   r   r
   )r   r   r'   )r   r7   )r   rS   )r   rW   r   r   )r   rC   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   )r(   r)   r*   r   r   propertyr|   r   setterr   r   r   r   r$   r   r~   r   r   r   r   r    r    r    r!   ry      sP    (

Q





	

ry   c                   @  s8   e Zd ZedddZddd	ZdddZdddZdS )
_MailMixinr   c.Iterator[list[Message]]c                 #  sJ    g  d
 fdd}t |  V  W d	   d	S 1 sw   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   r   rx   ry   r   r   c                   s     | d S r   )r   )r   rx   outboxr    r!   record     z*_MailMixin.record_messages.<locals>.recordN)r   r   rx   ry   r   r   )r   connected_to)r   r   r    r   r!   record_messages  s   "z_MailMixin.record_messagesrx   ry   r   c                 C  s8   |   }|| W d   dS 1 sw   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   rx   r   r    r    r!   r     s   
"z_MailMixin.sendr   r   r   c                 O  r   r   r   r   r    r    r!   r     s   z_MailMixin.send_messagerW   c              
   C  sD   t | ddpt}zt|jd W S  ty! } ztd|d}~ww )z$Opens a connection to the mail host.r   NrX   z:The current application was not configured with Flask-Mail)getattrr   rW   r   KeyErrorRuntimeError)r   r   errr    r    r!   r  (  s   z_MailMixin.connectN)r   r   )rx   ry   r   r   r   )r   rW   )r(   r)   r*   r   r  r   r   r  r    r    r    r!   r      s    



r   c                   @  s   e Zd ZdddZdS )_Mailrm   r"   ru   r   rv   rn   
int | Noners   rS   rj   r   rr   rq   r   r^   r   c                 C  sF   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	|| _
d S r   )rm   ru   rv   rn   rs   rj   r   rr   r   r^   r   )r   rm   ru   rv   rn   rs   rj   r   rr   r   r^   r   r    r    r!   r   5  s   
z_Mail.__init__N)rm   r"   ru   r   rv   r   rn   r	  rs   rS   rj   rS   r   r   rr   rq   r   r	  r^   rS   r   rS   )r(   r)   r*   r   r    r    r    r!   r  4  s    r  c                   @  s>   e Zd ZdZddddZ		ddddZdddZd ddZdS )!rY   zManages email messaging.Nr   Flask | Noner   r   c                 C  s(   || _ |d ur| || _d S d | _d S r   )r   init_appstate)r   r   r    r    r!   r   S  s   
zMail.__init__Fconfigdict[str, t.Any]rr   
bool | inttestingrS   r  c                 C  sp   t |dd|d|d|dd|dd|d	d|d
t|d||d|d||ddS )NMAIL_SERVERz	127.0.0.1MAIL_USERNAMEMAIL_PASSWORD	MAIL_PORT   MAIL_USE_TLSFMAIL_USE_SSLMAIL_DEFAULT_SENDER
MAIL_DEBUGMAIL_MAX_EMAILSMAIL_SUPPRESS_SENDMAIL_ASCII_ATTACHMENTS)r  r   rq   )r   r  rr   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   rX   )r  r  rr   r  r  r   )r   r   r  r    r    r!   r  l  s   
zMail.init_appnamer"   r   c                 C  s   t | j|d S r   )r  r  )r   r  r    r    r!   __getattr__y  r   zMail.__getattr__r   )r   r
  r   r   )FF)r  r  rr   r  r  rS   r   r  )r   r   r   r  r  r"   r   r   )r(   r)   r*   r   r   r  r  r  r    r    r    r!   rY   P  s    	
rY   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  s4   | dkrdd l }tjdtdd |jdS t| )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.   r"   r/   r"   r   r"   )r   )r=   r"   r.   r"   r   r"   )rB   rC   r.   r"   r   r"   )rM   rN   r.   r"   r   rO   )rR   r"   r   rS   r   )B
__future__r   collections.abcabccr   rk   r   typingtr   r   
contextlibr   emailr   r   email.encodersr   email.headerr   email.mime.baser   email.mime.multipartr	   email.mime.textr
   email.utilsr   r   r   r   	mimetypesr   typesr   blinkerflaskr   r   TYPE_CHECKINGtyping_extensionsteadd_charsetSHORTESTr8   r   r1   rA   rL   rQ   rV   rW   r9   r   r   ry   r   r  rY   	Namespacer!  __annotations__signalr   r  r    r    r    r!   <module>   sd    

[.  4-	