o
    ѷ6i6                     @   s   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ZG dd deZdS )    N)	timedelta)settings)mail)BaseCommand)Q)render_to_string)timezone)activate)
deactivate)models)app_settingsx   c                   @   sP   e Zd ZdZdZdd Zdd Zdd Zd	d
 Zdd Z	dd Z
	dddZdS )CommandTz[Sends notification emails to subscribed users taking into account the subscription intervalc                 C   s   |j dddddd |j dddd	d
d |j dddddd |j dddddd |j dddddd |j dddddd |j ddddd |j d dd!d"td |j d#dd$d%d d S )&Nz--daemonz-d
store_truedaemonzGo to daemon mode and exit)actiondesthelpz--cronz-ccronz/Do not loop, just send out emails once and exitz
--pid-filestorepidz!Where to write PID before exitingz/tmp/nyt_daemon.pid)r   r   r   defaultz--domaindomainz6Base domain to use for URLs (excluding HTTP protocol). z--http-onlyhttpz(Use http:// in URLs instead of https://.Fz
--log-filelogz!Where daemon should write its logz/tmp/nyt_daemon.logz--no-sys-exitno_sys_exitz@Skip sys-exit after forking daemon (mainly for testing purposes)z--daemon-sleep-interval
sleep_timez3Minimum sleep between each polling of the database.z--nownowzASimulate when to start sending from (mainly for testing purposes))add_argument
SLEEP_TIME)selfparser r#   n/var/www/hoanhtaovolam_webdjango/env/lib/python3.10/site-packages/django_nyt/management/commands/notifymail.pyadd_arguments    sz   
zCommand.add_argumentsc                 C   sz   t jr	tt j}nt||}|dd }t||}tj||t j|d j	g|d}| j
d|d j	  |jdd d S )N
r   user)
connectionzSending to: %sF)fail_silently)r   NYT_EMAIL_SUBJECTstrr   replacestripr   EmailMessageNYT_EMAIL_SENDERemailloggerinfosend)r!   template_nametemplate_subject_namecontextr(   subjectmessager0   r#   r#   r$   _render_and_send_   s   


zCommand._render_and_sendc              
   C   s   | j d zDt }|dkrE| j dt|  t| jd d}|t| W d    n1 s3w   Y  | jd sHt	d W d S W d S W d S  t
yn } ztjd|j|jf  t	d W Y d }~d S d }~ww )	NzDaemon mode enabled, forkingr   zPID: %sr   wr   zfork failed: %d (%s)
   )r1   r2   osforkr+   openoptionswritesysexitOSErrorstderrerrnostrerror)r!   fpidpid_fileer#   r#   r$   
_daemonizew   s"   
zCommand._daemonizec                 O   s  t tj |dd |dd |dd || _|d }|d }|r*|r*J dtd| _| jjs[|r?tj	|d d}nt
| j}|td	d
 | j| | jtj | jd tjsn| jd t  |rt|   t }|r| jdr| jd}| jd|  nt }| || d S |std z| |t|d  W n t y   td Y nw t!  d S )Nr   Fr   r   z.You cannot both choose cron and daemon options
django_nytr   )filenamez(%(asctime)s: %(levelname)s - %(message)sz%Y-%m-%d %H:%M:%Sz%Starting django_nyt e-mail dispatcherzE-mails disabled - quitting.r   zusing now: z"Entering send-loop, CTRL+C to exitr   z
Quitting...)"r	   r   LANGUAGE_CODE
setdefaultr?   logging	getLoggerr1   handlersFileHandlerStreamHandlerstdoutsetFormatter	Formatter
addHandlersetLevelINFOr2   r   NYT_SEND_EMAILSrA   rB   rJ   r   get_connectiongetr   r   
send_mailsprint	send_loopintKeyboardInterruptr
   )r!   argsr?   r   r   handlerr(   r   r#   r#   r$   handle   sT   

zCommand.handlec                 C   s   d }	 t  }| jdt|  |r0tjjj|| j	d d d
d}| jdp.t  }nt  }d }| j||||d |  t  }t| q)NTzStarting send loop at %s<   )interval__lter'   r   )	last_sentuser_settings)r   r   r1   r2   r+   r   Settingsobjectsfiltersecondsorder_byr?   r\   r]   closetimesleep)r!   r(   r   rg   started_sending_atrh   r   r#   r#   r$   r_      s(   
zCommand.send_loopc           
   
   C   sB  |d }t |d dkrdS 	 dd |D }z9| jd|  | |||| |D ]}d|_|  t |j_	|j  q*t
jjj|djt d	 W dS  tjyd   | jd
|jj Y q tjy }	 z| jd|	 | jd td W Y d}	~	nd}	~	w ty }	 z
| jd|	  d}	~	ww q)zn
        Loops through emails in a list of notifications and tries to send
        to each recipient

        notificationsr   NTc                 S   s   g | ]}|j qS r#   )id).0nr#   r#   r$   
<listcomp>   s    z,Command._send_with_retry.<locals>.<listcomp>zSending to notification ids )notification__id__inrg   z-E-mail refused by SMTP server ({}), skipping!z@You have an error with your SMTP server connection, error is: {}z!Sleeping for 30s then retrying...   z0Unhandled exception while sending, giving up: {})lenr1   r2   r9   
is_emailedsaver   r   subscriptionrg   r   Subscriptionrj   rk   updatesmtplibSMTPSenderRefusederrorformatr'   r0   SMTPExceptionro   rp   	Exception)
r!   r4   subject_template_namer6   r(   settingrr   notification_idsru   rI   r#   r#   r$   _send_with_retry   sX   	zCommand._send_with_retryNc              
   C   s  | j d| d| d |  |s#tjj ddd	d}| j
d r0d}| j
d }nd	d
lm} |j }|j}| j
d rFd}nd}|D ]}	|t|	jd }
dddd|||d}|	j|d< t|	j|	jj|d< dd tjD |	j}tj| d |d< i }t }|	jrtt|
dtdd@ tt|
dtdd@ B }|	jj|dd	dD ]=}z|j }W n tjjy   | j d|j  Y qw |j  }|!||fg  |||f  t"|j#jdd7  < q|$ D ]\\}}}|sq||d< | %|||||	 qqJdS )z
        Does the lookups and sends out email digests to anyone who has them due.
        Since the system may have different templates depending on which notification is being sent,
        we will generate a call for each template.
        zEntering send_mails(now=z, last_sent=z, ...)r'   subscription_set#subscription_set__notification_typer   Nr   )Siter   https)minutes)r'   usernamerr   digestsiter   http_schemer   c                 S   s   g | ]}|d  qS )r   r#   )rt   yr#   r#   r$   rv   Q  s    z&Command.send_mails.<locals>.<listcomp>r;   r   )created__lterx   )last_sent__lteF)latest__is_emailedT)send_emailsnotification_type__keyz0Subscription has non-existent notification type )r{   rr   )&r1   debugr>   r   ri   rj   allselect_relatedprefetch_relatedrm   r?   django.contrib.sites.modelsr   get_currentr   r   intervalr'   getattrUSERNAME_FIELDr   NYT_INTERVALSindexr   r   rk   notification_typeget_email_template_nameNotificationTypeDoesNotExistwarningnotification_type_idget_email_subject_template_namerN   listnotification_setitemsr   )r!   r(   r   rg   rh   site_objectr   r   r   r   	thresholdr6   idxemails_per_template	filter_qsr}   r4   r   rr   r#   r#   r$   r]     s   	

	




	

zCommand.send_mails)NN)__name__
__module____qualname__can_import_settingsr   r%   r9   rJ   rd   r_   r   r]   r#   r#   r#   r$   r      s    ??5r   )rO   r<   r   rA   ro   datetimer   django.confr   django.corer   django.core.management.baser   django.db.modelsr   django.template.loaderr   django.utilsr   django.utils.translationr	   r
   rK   r   django_nyt.confr   r    r   r#   r#   r#   r$   <module>   s$    