o
    ›¨Êh¹Y  ã                   @   sì   d dl Z d dlmZmZ d dlZd dlmZ d dlmZ d dlm	Z	m
Z
mZmZ d dlmZ ddlmZmZmZmZmZ dd	lmZ dd
lmZmZ ddlmZmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z% G dd„ deƒZ&G dd„ de'ƒZ(dS )é    N)ÚdateÚdatetime)Úsettings)ÚBaseEmailBackend)Úis_naiveÚget_current_timezoneÚ
make_awareÚutc)ÚCaseInsensitiveDicté   )ÚAnymailCancelSendÚAnymailErrorÚAnymailUnsupportedFeatureÚAnymailRecipientsRefusedÚAnymailSerializationError)ÚAnymailStatus)Úpre_sendÚ	post_send)Ú
AttachmentÚUNSETÚcombineÚlastÚget_anymail_settingÚparse_address_listÚparse_single_addressÚforce_non_lazyÚforce_non_lazy_listÚforce_non_lazy_dictÚis_lazyc                       s|   e Zd ZdZ‡ fdd„Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZ‡  ZS )ÚAnymailBaseBackendz$
    Base Anymail email backend
    c                    sx   t t| ƒj|i |¤Ž td|dd�| _td|dd�| _tdi d�}td| j|d d�}|d ur7| ¡ }| |¡ || _	d S )NÚignore_unsupported_featuresF)ÚkwargsÚdefaultÚignore_recipient_statusÚsend_defaults©r"   )Úesp_namer!   r"   )
Úsuperr   Ú__init__r   r    r#   r&   ÚcopyÚupdater$   )ÚselfÚargsr!   r$   Úesp_send_defaults©Ú	__class__© úG/var/www/html/env/lib/python3.10/site-packages/anymail/backends/base.pyr(      s   ÿÿÿ

zAnymailBaseBackend.__init__c                 C   ó   dS )zÓ
        Open and persist a connection to the ESP's API, and whether
        a new connection was created.

        Callers must ensure they later call close, if (and only if) open
        returns True.
        Fr0   ©r+   r0   r0   r1   Úopen*   s   zAnymailBaseBackend.openc                 C   r2   )z�
        Close the cached connection created by open.

        You must only call close if your code called open and it returned True.
        Nr0   r3   r0   r0   r1   Úclose>   s   zAnymailBaseBackend.closec              	   C   s~   d}|s|S |   ¡ }z,|D ] }z|  |¡}W n ty&   | jr#d}n‚ Y nw |r-|d7 }qW |r5|  ¡  |S |r>|  ¡  w w )zo
        Sends one or more EmailMessage objects and returns the number of email
        messages sent.
        r   Fé   )r4   Ú_sendr   Úfail_silentlyr5   )r+   Úemail_messagesÚnum_sentÚcreated_sessionÚmessageÚsentr0   r0   r1   Úsend_messagesK   s0   	þþ€÷ý
ÿz AnymailBaseBackend.send_messagesc                 C   s~   t ƒ |_|  |¡sdS | ¡ sdS |  || j¡}|  ||¡}||j_|  |||¡}|j 	|¡ |  
|¡ |  |j|||¡ dS )a1  Sends the EmailMessage message, and returns True if the message was sent.

        This should only be called by the base send_messages loop.

        Implementations must raise exceptions derived from AnymailError for
        anticipated failures that should be suppressed in fail_silently mode.
        FT)r   Úanymail_statusÚrun_pre_sendÚ
recipientsÚbuild_message_payloadr$   Úpost_to_espÚesp_responseÚparse_recipient_statusÚset_recipient_statusÚrun_post_sendÚraise_for_recipient_status)r+   r<   ÚpayloadÚresponseÚrecipient_statusr0   r0   r1   r7   k   s   

zAnymailBaseBackend._sendc                 C   s0   zt j| j|| jd� W dS  ty   Y dS w )zESend pre_send signal, and return True if message should still be sent)r<   r&   TF)r   Úsendr/   r&   r   )r+   r<   r0   r0   r1   r@   †   s   ÿzAnymailBaseBackend.run_pre_sendc                 C   s8   t j| j||j| jd�}|D ]\}}t|tƒr|‚qdS )z&Send post_send signal to all receivers)r<   Ústatusr&   N)r   Úsend_robustr/   r?   r&   Ú
isinstanceÚ	Exception)r+   r<   ÚresultsÚreceiverrJ   r0   r0   r1   rG   Ž   s   ÿ
ÿÿz AnymailBaseBackend.run_post_sendc                 C   ó   t d| jj| jjf ƒ‚)a¥  Returns a payload that will allow message to be sent via the ESP.

        Derived classes must implement, and should subclass :class:BasePayload
        to get standard Anymail options.

        Raises :exc:AnymailUnsupportedFeature for message options that
        cannot be communicated to the ESP.

        :param message: :class:EmailMessage
        :param defaults: dict
        :return: :class:BasePayload
        z*%s.%s must implement build_message_payload©ÚNotImplementedErrorr/   Ú
__module__Ú__name__)r+   r<   Údefaultsr0   r0   r1   rB   –   s   ÿz(AnymailBaseBackend.build_message_payloadc                 C   rS   )a3  Post payload to ESP send API endpoint, and return the raw response.

        payload is the result of build_message_payload
        message is the original EmailMessage
        return should be a raw response

        Can raise AnymailAPIError (or derived exception) for problems posting to the ESP
        z %s.%s must implement post_to_esprT   )r+   rI   r<   r0   r0   r1   rC   ¦   ó   	ÿzAnymailBaseBackend.post_to_espc                 C   rS   )z¦Return a dict mapping email to AnymailRecipientStatus for each recipient.

        Can raise AnymailAPIError (or derived exception) if response is unparsable
        z+%s.%s must implement parse_recipient_statusrT   )r+   rJ   rI   r<   r0   r0   r1   rE   ²   s   ÿz)AnymailBaseBackend.parse_recipient_statusc                 C   s.   | j s|j ddh¡rt|||| d�‚dS dS )zKIf *all* recipients are refused or invalid, raises AnymailRecipientsRefusedÚinvalidÚrejected)Úemail_messagerI   rJ   ÚbackendN)r#   rM   Úissubsetr   )r+   r?   rJ   rI   r<   r0   r0   r1   rH   º   s   ÿüz-AnymailBaseBackend.raise_for_recipient_statusc                 C   rS   )zé
        Read-only name of the ESP for this backend.

        Concrete backends must override with class attr. E.g.:
            esp_name = "Postmark"
            esp_name = "SendGrid"  # (use ESP's preferred capitalization)
        z&%s.%s must declare esp_name class attrrT   r3   r0   r0   r1   r&   Ã   rY   zAnymailBaseBackend.esp_name)rW   rV   Ú__qualname__Ú__doc__r(   r4   r5   r>   r7   r@   rG   rB   rC   rE   rH   Úpropertyr&   Ú__classcell__r0   r0   r.   r1   r      s     	r   c                   @   sä  e Zd Zdeefdeefdeefdeefdeefdeefdeefdeefd	ed
fdedff
Zdee	fdeefdedfdee
fdedfdedfdeefdeefdeefdeeff
ZdZdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ Zd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Zd8d9„ Zd:d;„ Zd<d=„ Zd>d?„ Zd@dA„ Z dBdC„ Z!dDdE„ Z"dFdG„ Z#dHdI„ Z$dJdK„ Z%dLdM„ Z&dNdO„ Z'dPdQ„ Z(dRdS„ Z)dTdU„ Z*dVdW„ Z+dXdY„ Z,dZd[„ Z-d\d]„ Z.d^d_„ Z/d`da„ Z0e1dbdc„ ƒZ2dS )dÚBasePayloadÚ
from_emailÚtoÚccÚbccÚsubjectÚreply_toÚextra_headersÚbodyÚalternativesÚprepped_alternativesÚattachmentsÚprepped_attachmentsÚenvelope_senderÚmetadataÚsend_atÚaware_datetimeÚtagsÚtrack_clicksNÚtrack_opensÚtemplate_idÚ
merge_dataÚmerge_global_dataÚ	esp_extrar0   c                 C   s2  || _ || _|| _|j| _|  ¡  | j| j | j }|D ]z\}}}t||t	ƒ}|dv r5|t	ur5|  
||¡ |d urE| j |t	¡}	||	|ƒ}|t	urg|d urgt|ƒsVt| |ƒ}|ttfv rc|||d�}n||ƒ}|t	ur–|dkr{|jdkrw| jn| j}
n|dkrƒ| j}
n|dkr‹| j}
nt| d| ƒ}
|
|ƒ qd S )N)re   rf   rg   ri   ©Úfieldrk   Úhtmlrd   rj   zset_%s)r<   rX   r]   r&   Úinit_payloadÚbase_message_attrsÚanymail_message_attrsÚesp_message_attrsÚgetattrr   Úvalidate_not_bare_stringÚgetÚcallabler   r   Úcontent_subtypeÚset_html_bodyÚset_text_bodyÚset_from_email_listÚprocess_extra_headers)r+   r<   rX   r]   Úmessage_attrsÚattrÚcombinerÚ	converterÚvalueÚdefault_valueÚsetterr0   r0   r1   r(   ú   s>   

€æzBasePayload.__init__c                 C   s*   | j jstd| j|f | j| | j d�‚d S )Nz%s does not support %s)r\   rI   r]   )r]   r    r   r&   r<   )r+   Úfeaturer0   r0   r1   Úunsupported_feature   s
   
ÿÿzBasePayload.unsupported_featurec                 C   sœ   t |ƒ}| dd ¡}|r|  t|gdd�¡ d|v r5t| d¡dd�}t| jjdd�}|  |¡ |  |¡ d|v rC| d¡}|  	|¡ |rL|  
|¡ d S d S )NzReply-Tozextra_headers['Reply-To']r{   ÚFromzextra_headers['From']rd   ÚTo)r
   ÚpopÚset_reply_tor   r   r<   rd   r‰   Úset_envelope_senderÚset_spoofed_to_headerÚset_extra_headers)r+   Úheadersri   Úheader_fromrp   Ú	header_tor0   r0   r1   rŠ   %  s   



ÿz!BasePayload.process_extra_headersc                 C   s(   t |tjƒs
t|ƒrtdj|d�ƒ‚dS )zÕEmailMessage to, cc, bcc, and reply_to are specced to be lists of strings.

        This catches the common error where a single string is used instead.
        (See also checks in EmailMessage.__init__.)
        z3"{attr}" attribute must be a list or other iterable)rŒ   N)rO   ÚsixÚstring_typesr   Ú	TypeErrorÚformat)r+   rŒ   r�   r0   r0   r1   rƒ   M  s   ÿz$BasePayload.validate_not_bare_stringc                 C   s   dd„ |D ƒS )Nc                 S   s   g | ]
\}}t |ƒ|f‘qS r0   )r   )Ú.0ÚcontentÚmimetyper0   r0   r1   Ú
<listcomp>b  s    ÿz4BasePayload.prepped_alternatives.<locals>.<listcomp>r0   )r+   rl   r0   r0   r1   rm   a  s   ÿz BasePayload.prepped_alternativesc                    s    | j jptj‰ ‡ fdd„|D ƒS )Nc                    s   g | ]}t |ˆ ƒ‘qS r0   )r   )r¢   Ú
attachment©Ústr_encodingr0   r1   r¥   g  s    ÿz3BasePayload.prepped_attachments.<locals>.<listcomp>)r<   Úencodingr   ÚDEFAULT_CHARSET)r+   rn   r0   r§   r1   ro   e  s   
ÿzBasePayload.prepped_attachmentsc              	   C   sx   t |tƒr|}n(t |tƒrt|j|j|jƒ}nzt |¡jtd�}W n t	t
fy/   | Y S w t|ƒr:t|tƒ ƒ}|S )a‡  Converts a date or datetime or timestamp to an aware datetime.

        Naive datetimes are assumed to be in Django's current_timezone.
        Dates are interpreted as midnight that date, in Django's current_timezone.
        Integers are interpreted as POSIX timestamps (which are inherently UTC).

        Anything else (e.g., str) is returned unchanged, which won't be portable.
        )Útzinfo)rO   r   r   ÚyearÚmonthÚdayÚutcfromtimestampÚreplacer	   r    Ú
ValueErrorr   r   r   )r+   r�   Údtr0   r0   r1   rs   j  s   
	
ÿzBasePayload.aware_datetimec                 C   rS   )Nz!%s.%s must implement init_payloadrT   r3   r0   r0   r1   r~   …  ó   ÿzBasePayload.init_payloadc                 C   s8   t |ƒdkr|  d¡ t |ƒdkr|  |d ¡ d S d S )Nr6   zmultiple from emailsr   )Úlenr“   Úset_from_email©r+   Úemailsr0   r0   r1   r‰   ‰  s
   
ÿzBasePayload.set_from_email_listc                 C   rS   )Nz:%s.%s must implement set_from_email or set_from_email_listrT   ©r+   Úemailr0   r0   r1   rµ   ’  r³   zBasePayload.set_from_emailc                 C   ó   |   d|¡S )Nre   ©Úset_recipientsr¶   r0   r0   r1   Úset_to–  ó   zBasePayload.set_toc                 C   rº   )Nrf   r»   r¶   r0   r0   r1   Úset_cc™  r¾   zBasePayload.set_ccc                 C   rº   )Nrg   r»   r¶   r0   r0   r1   Úset_bccœ  r¾   zBasePayload.set_bccc                 C   s   |D ]}|   ||¡ qd S ©N)Úadd_recipient)r+   Úrecipient_typer·   r¹   r0   r0   r1   r¼   Ÿ  s   ÿzBasePayload.set_recipientsc                 C   rS   )NzF%s.%s must implement add_recipient, set_recipients, or set_{to,cc,bcc}rT   )r+   rÃ   r¹   r0   r0   r1   rÂ   £  r³   zBasePayload.add_recipientc                 C   rS   )Nz %s.%s must implement set_subjectrT   )r+   rh   r0   r0   r1   Úset_subject§  r³   zBasePayload.set_subjectc                 C   ó   |   d¡ d S )Nri   ©r“   r¶   r0   r0   r1   r—   «  ó   zBasePayload.set_reply_toc                 C   rÅ   )Nrj   rÆ   )r+   r›   r0   r0   r1   rš   ®  s   zBasePayload.set_extra_headersc                 C   rS   )Nz"%s.%s must implement set_text_bodyrT   ©r+   rk   r0   r0   r1   rˆ   ²  r³   zBasePayload.set_text_bodyc                 C   rS   )Nz"%s.%s must implement set_html_bodyrT   rÈ   r0   r0   r1   r‡   ¶  r³   zBasePayload.set_html_bodyc                 C   s2   |D ]\}}|dkr|   |¡ q|  ||¡ qd S )Nz	text/html)r‡   Úadd_alternative)r+   rl   r£   r¤   r0   r0   r1   Úset_alternativesº  s
   ùzBasePayload.set_alternativesc                 C   s   |   d| ¡ d S )Nzalternative part with type '%s'rÆ   )r+   r£   r¤   r0   r0   r1   rÉ   Ä  s   zBasePayload.add_alternativec                 C   s   |D ]}|   |¡ qd S rÁ   )Úadd_attachment)r+   rn   r¦   r0   r0   r1   Úset_attachmentsÇ  s   ÿzBasePayload.set_attachmentsc                 C   rS   )Nz6%s.%s must implement add_attachment or set_attachmentsrT   )r+   r¦   r0   r0   r1   rË   Ë  r³   zBasePayload.add_attachmentc                 C   rÅ   )Nzspoofing `To` headerrÆ   )r+   r�   r0   r0   r1   r™   Ï  s   z!BasePayload.set_spoofed_to_headerc                 C   rÅ   )Nrp   rÆ   r¸   r0   r0   r1   r˜   Õ  rÇ   zBasePayload.set_envelope_senderc                 C   rÅ   )Nrq   rÆ   )r+   rq   r0   r0   r1   Úset_metadataØ  rÇ   zBasePayload.set_metadatac                 C   rÅ   )Nrr   rÆ   )r+   rr   r0   r0   r1   Úset_send_atÛ  rÇ   zBasePayload.set_send_atc                 C   rÅ   )Nrt   rÆ   )r+   rt   r0   r0   r1   Úset_tagsÞ  rÇ   zBasePayload.set_tagsc                 C   rÅ   )Nru   rÆ   )r+   ru   r0   r0   r1   Úset_track_clicksá  rÇ   zBasePayload.set_track_clicksc                 C   rÅ   )Nrv   rÆ   )r+   rv   r0   r0   r1   Úset_track_opensä  rÇ   zBasePayload.set_track_opensc                 C   rÅ   )Nrw   rÆ   )r+   rw   r0   r0   r1   Úset_template_idç  rÇ   zBasePayload.set_template_idc                 C   rÅ   )Nrx   rÆ   )r+   rx   r0   r0   r1   Úset_merge_dataê  rÇ   zBasePayload.set_merge_datac                 C   rÅ   )Nry   rÆ   )r+   ry   r0   r0   r1   Úset_merge_global_dataí  rÇ   z!BasePayload.set_merge_global_datac                 C   rÅ   )Nrz   rÆ   )r+   Úextrar0   r0   r1   Úset_esp_extrañ  rÇ   zBasePayload.set_esp_extrac              
   C   s@   z	t j|| jd�W S  ty } z
t|| j| j| d�‚d}~ww )zÍReturns data serialized to json, raising appropriate errors.

        Essentially json.dumps with added context in any errors.

        Useful for implementing, e.g., serialize_data in a subclass,
        r%   )Úorig_errr\   r]   rI   N)ÚjsonÚdumpsÚ_json_defaultr    r   r<   r]   )r+   ÚdataÚerrr0   r0   r1   Úserialize_jsonø  s   ÿ€þzBasePayload.serialize_jsonc                 C   s"   t | tƒr	t| ƒS td| jj ƒ‚)zFjson.dump default function that handles some common Payload data typesz,Object of type '%s' is not JSON serializable)rO   r
   Údictr    r/   rW   )Úor0   r0   r1   rÚ     s
   
ÿzBasePayload._json_default)3rW   rV   r_   r   r   r   r   r   r   r   r   r€   r�   r(   r“   rŠ   rƒ   rm   ro   rs   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Ý   ÚstaticmethodrÚ   r0   r0   r0   r1   rc   Ð   s|    õõ&(	
rc   ))rØ   r   r   rž   Údjango.confr   Údjango.core.mail.backends.baser   Údjango.utils.timezoner   r   r   r	   Úrequests.structuresr
   Ú
exceptionsr   r   r   r   r   r<   r   Úsignalsr   r   Úutilsr   r   r   r   r   r   r   r   r   r   r   r   Úobjectrc   r0   r0   r0   r1   Ú<module>   s    4 =