o 3aB@sddlZddlmZmZmZmZddlm Z ddl m Z ddl m Z mZddlmZddlmZddlmZdd lmZdd lmZdd lmZmZmZmZdd lmZm Z dd l!m"Z"ddl#m$Z$ddl%m&Z&ddl'm(Z(m)Z)edZ*de*_+edZ,ej-e,_+dZ.dZ/Gddde0Z1hdZ2ddZ3ddZ4GdddZ5Gddde5eZ6Gdd d e5eZ7Gd!d"d"e5eZ8Gd#d$d$Z9Gd%d&d&e9Z:dS)'N)charsetencoders generatormessage_from_string)HeaderParseError)Header)Addressparser)Message)MIMEBase) MIMEMessage) MIMEMultipart)MIMEText) formataddr formatdate getaddresses make_msgid)BytesIOStringIO)Path)settings)DNS_NAME) force_strpunycodeutf-8zapplication/octet-streamic@s eZdZdS)BadHeaderErrorN)__name__ __module__ __qualname__rr:/usr/lib/python3/dist-packages/django/core/mail/message.pyr#sr> reply-to resent-cc resent-to resent-bcc resent-from resent-sendercctobccfromsendercsptjt|}d|vsd|vrtd||fz|dWn.tyN|tvr=dfddt |fD}n t |}Y||fSY||fSw|dkr[t |}||fS) z6Forbid multi-line headers to prevent header injection.  z;Header values can't contain newlines (got %r for header %r)ascii, c3s|]}t|VqdSN)sanitize_address).0addrencodingrr Asz,forbid_multi_line_headers..subject) rDEFAULT_CHARSETstrrencodeUnicodeEncodeErrorlowerADDRESS_HEADERSjoinrr)namevalr5rr4r forbid_multi_line_headers7s"      rAc CsDd}t|ts=t|}z t|\}}Wntttfy$td|w|r/td||f|jp3d}|j }|j p;d}n |\}}| dd\}}|||}d|vsWd|vr[td z | d t | }Wntyxt || }Ynwz| d Wntyt || }Ynwt|}t||d } t|| jfS) zF Format a pair of (name, address) or an email address string. NzInvalid address "%s"z2Invalid address; only %s could be parsed from "%s"@r,r-z7Invalid address; address parts cannot contain newlines.r.)usernamedomain) isinstancetuplerr get_mailboxr ValueError IndexError display_name local_partrFrsplitr:rr;rrr addr_spec) r3r5addresstokenrestnm localpartrF address_partsparsed_addressrrr r1JsH         r1c@s eZdZdddZdddZdS) MIMEMixinFr,cC,t}tj|dd}|j|||d|S)a&Return the entire formatted message as a string. Optional `unixfrom' when True, means include the Unix From_ envelope header. This overrides the default as_string() implementation to not mangle lines that begin with 'From '. See bug #13433 for details. F mangle_from_unixfromlinesep)rr Generatorflattengetvalueselfr\r]fpgrrr as_stringxzMIMEMixin.as_stringcCrX)a"Return the entire formatted message as bytes. Optional `unixfrom' when True, means include the Unix From_ envelope header. This overrides the default as_bytes() implementation to not mangle lines that begin with 'From '. See bug #13433 for details. FrYr[)rrBytesGeneratorr_r`rarrr as_bytesrfzMIMEMixin.as_bytesN)Fr,)rrrrerhrrrr rWws  rWc@seZdZddZdS)SafeMIMEMessagecCs"t||d\}}t|||dS)Nr.)rAr __setitem__rbr?r@rrr rjszSafeMIMEMessage.__setitem__N)rrrrjrrrr ris ric@s(eZdZd ddZddZd ddZdS) SafeMIMETextplainNcCs||_tj||||ddS)N)_subtype_charset)r5r__init__)rb_textrnrorrr rpszSafeMIMEText.__init__cC$t|||j\}}t|||dSr0)rAr5rrjrkrrr rjzSafeMIMEText.__setitem__cCsJ|dkrt|tjstdd|D}|rtnt}tj|||ddS)Nrcss |] }t|tkVqdSr0)lenr:RFC5322_EMAIL_LINE_LENGTH_LIMIT)r2linerrr r6s  z+SafeMIMEText.set_payload..)r)rGCharsetany splitlinesutf8_charset_qp utf8_charsetr set_payload)rbpayloadrhas_long_linesrrr r|s  zSafeMIMEText.set_payload)rmNr0)rrrrprjr|rrrr rls rlc@seZdZdddZddZdS)SafeMIMEMultipartmixedNcKs"||_tj||||fi|dSr0)r5r rp)rbrnboundary _subpartsr5_paramsrrr rpszSafeMIMEMultipart.__init__cCrrr0)rAr5r rjrkrrr rjrszSafeMIMEMultipart.__setitem__)rNNN)rrrrprjrrrr rs  rc@seZdZdZdZdZdZ   dddZd d d Zd d Z d dZ d ddZ d!ddZ d"ddZ ddZddZddZd"ddZddZdS)# EmailMessagez"A container for email information.rmrNrBc Cs|rt|tr tdt||_ng|_| r%t| trtdt| |_ng|_|r9t|tr3tdt||_ng|_| rMt| trGtdt| |_ng|_|pTtj |_ ||_ |p\d|_ g|_ |rx|D]} t| trr|| qe|j| qe|p{i|_||_dS)g Initialize a single email message (which can be sent to multiple recipients). z%"to" argument must be a list or tuplez%"cc" argument must be a list or tuplez&"bcc" argument must be a list or tuplez+"reply_to" argument must be a list or tuplerBN)rGr9 TypeErrorlistr(r'r)reply_torDEFAULT_FROM_EMAIL from_emailr7body attachmentsr attach extra_headers connection) rbr7rrr(r)rrheadersr'r attachmentrrr rps>               zEmailMessage.__init__FcCs$ddlm}|js||d|_|jS)Nr)get_connection) fail_silently)django.core.mailrr)rbrrrrr rs  zEmailMessage.get_connectioncCs|jptj}t|j|j|}||}|j|d<|j d|j |d<| |d|j | |d|j | |d|jdd|jD}d|vrNttjd |d <d |vrYttd |d <|jD]\}}|dkrl|||<q^|S)NSubjectFromToCczReply-TocSsg|]}|qSr)r<)r2keyrrr z(EmailMessage.message..date) localtimeDatez message-id)rFz Message-IDr*)r5rr8rlrcontent_subtype_create_messager7rgetr_set_list_header_if_not_emptyr(r'rrEMAIL_USE_LOCALTIMErritemsr<)rbr5msg header_namesr?valuerrr messages$    zEmailMessage.messagecCsdd|j|j|jDS)z Return a list of all recipients of the email (includes direct addressees as well as Cc and Bcc entries). cSsg|]}|r|qSrr)r2emailrrr rrz+EmailMessage.recipients..)r(r'r))rbrrr recipientsszEmailMessage.recipientscCs|sdS|||gS)zSend the email message.r)rr send_messages)rbrrrr sendszEmailMessage.sendcCst|tr|dus J|dusJ|j|dS|dusJ|p)t|dp)t}|dd\}}|dkrMt|trMz| }Wn t yLt}Ynw|j|||fdS)a Attach a file with the given filename and content. The filename can be omitted and the mimetype is guessed, if not provided. If the first parameter is a MIMEBase subclass, insert it directly into the resulting message attachments. For a text/* mimetype (guessed or specified), when a bytes object is specified as content, decode it as UTF-8. If that fails, set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE and don't decode the content. Nr/rDtext) rGr rappend mimetypes guess_typeDEFAULT_ATTACHMENT_MIME_TYPEsplitbytesdecodeUnicodeDecodeError)rbfilenamecontentmimetypebasetypesubtyperrr rs      zEmailMessage.attachcCsPt|}|d}|}||j||WddS1s!wYdS)al Attach a file from the filesystem. Set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE if it isn't specified and cannot be guessed. For a text/* mimetype (guessed or specified), decode the file's content as UTF-8. If that fails, set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE and don't decode the content. rbN)ropenreadrr?)rbpathrfilerrrr attach_file>s  "zEmailMessage.attach_filecCs ||Sr0)_create_attachmentsrbrrrr rNs zEmailMessage._create_messagecCsr|jr7|jptj}|}t|j|d}|js|r|||jD]}t |t r.||q!||j |q!|SN)rnr5) rr5rr8r mixed_subtyper is_multipartrrGr _create_attachment)rbrr5body_msgrrrr rQs     z EmailMessage._create_attachmentscCs|dd\}}|dkr|jptj}t|||}|S|dkr>|dkr>t|tr,|}n t|ts7t t |}t ||}|St ||}| |t||S)z Convert the content, mimetype pair into a MIME attachment object. If the mimetype is message/rfc822, content may be an email.Message or EmailMessage object, as well as a str. rrDrrrfc822)rr5rr8rlrGrrr rrrir r|Encoders encode_base64)rbrrrrr5rrrr _create_mime_attachment_s          z$EmailMessage._create_mime_attachmentcCsP|||}|r&z|dWntydd|f}Ynw|jdd|d|S)zg Convert the filename, content, mimetype triple into a MIME attachment object. r.rrBzContent-Dispositionr)r)rr:r; add_header)rbrrrrrrr r}s  zEmailMessage._create_attachmentcCsJ|r#z|j|}Wntyddd|D}Ynw|||<dSdS)zt Set msg's header, either from self.extra_headers, if present, or from the values argument. r/css|]}t|VqdSr0)r9)r2vrrr r6sz=EmailMessage._set_list_header_if_not_empty..N)rKeyErrorr>)rbrheadervaluesrrrr rs  z*EmailMessage._set_list_header_if_not_empty) rBrBNNNNNNNN)F)NNNr0)rrr__doc__rrr5rprrrrrrrrrrrrrrr rs( ,     rcsDeZdZdZdZ   d fdd ZddZd d Zd d ZZ S)EmailMultiAlternativesz A version of EmailMessage that makes it easy to send multipart/alternative messages. For example, including text and HTML versions of the text is made easier. alternativerBNc s,t||||||||| | | pg|_dS)rN)superrp alternatives) rbr7rrr(r)rrrrr'r __class__rr rps zEmailMultiAlternatives.__init__cCs,|dusJ|dus J|j||fdS)z-Attach an alternative content representation.N)rr)rbrrrrr attach_alternatives  z)EmailMultiAlternatives.attach_alternativecCs|||Sr0)r_create_alternativesrrrr rsz&EmailMultiAlternatives._create_messagecCsT|jptj}|jr(|}t|j|d}|jr|||jD] }||j|q|Sr) r5rr8rralternative_subtyperrr)rbrr5rrrrr rs   z+EmailMultiAlternatives._create_alternatives) rBrBNNNNNNNNN) rrrrrrprrr __classcell__rrrr rs r);rrrrwrrrr email.errorsr email.headerremail.headerregistryrr email.messager email.mime.baser email.mime.messager email.mime.multipartr email.mime.textr email.utilsrrrriorrpathlibr django.confrdjango.core.mail.utilsrdjango.utils.encodingrrr{ body_encodingrzQPrrurJrr=rAr1rWrirlrrrrrrr sB            - ]