3636DOI_REGEX = re .compile (r'10\.\d{4,9}/[-._;()/:A-Z0-9]+' , re .IGNORECASE )
3737CACHE_DIR = Path (tempfile .gettempdir ()) / 'optimap_cache'
3838
39+ def _get_article_link (pub ):
40+ """
41+ Return the DOI resolver URL if pub.doi is set, otherwise fall back to pub.url.
42+ """
43+ return f"https://doi.org/{ pub .doi } " if pub .doi else pub .url
3944
4045def generate_data_dump_filename (extension : str ) -> str :
4146 ts = datetime .now (dt_timezone .utc ).strftime ("%Y%m%dT%H%M%S" )
@@ -247,15 +252,20 @@ def harvest_oai_endpoint(source_id: int, user=None) -> None:
247252
248253
249254def send_monthly_email (trigger_source = 'manual' , sent_by = None ):
250- recipients = User .objects .filter (userprofile__notify_new_manuscripts = True ).values_list ('email' , flat = True )
255+ recipients = User .objects .filter (userprofile__notify_new_manuscripts = True ) \
256+ .values_list ('email' , flat = True )
251257 last_month = timezone .now ().replace (day = 1 ) - timedelta (days = 1 )
252258 new_manuscripts = Publication .objects .filter (creationDate__month = last_month .month )
253259
254260 if not recipients .exists () or not new_manuscripts .exists ():
255261 return
256262
257263 subject = "📚 New Manuscripts This Month"
258- content = "Here are the new manuscripts:\n " + "\n " .join ([pub .title for pub in new_manuscripts ])
264+ lines = []
265+ for pub in new_manuscripts :
266+ link = _get_article_link (pub )
267+ lines .append (f"- { pub .title } : { link } " )
268+ content = "Here are the new manuscripts:\n " + "\n " .join (lines )
259269
260270 for recipient in recipients :
261271 try :
@@ -267,14 +277,25 @@ def send_monthly_email(trigger_source='manual', sent_by=None):
267277 fail_silently = False ,
268278 )
269279 EmailLog .log_email (
270- recipient , subject , content , sent_by = sent_by , trigger_source = trigger_source , status = "success"
280+ recipient ,
281+ subject ,
282+ content ,
283+ sent_by = sent_by ,
284+ trigger_source = trigger_source ,
285+ status = "success"
271286 )
272287 time .sleep (settings .EMAIL_SEND_DELAY )
273288 except Exception as e :
274289 error_message = str (e )
275290 logger .error (f"Failed to send monthly email to { recipient } : { error_message } " )
276291 EmailLog .log_email (
277- recipient , subject , content , sent_by = sent_by , trigger_source = trigger_source , status = "failed" , error_message = error_message
292+ recipient ,
293+ subject ,
294+ content ,
295+ sent_by = sent_by ,
296+ trigger_source = trigger_source ,
297+ status = "failed" ,
298+ error_message = error_message
278299 )
279300
280301def send_subscription_based_email (trigger_source = 'manual' , sent_by = None , user_ids = None ):
@@ -284,19 +305,24 @@ def send_subscription_based_email(trigger_source='manual', sent_by=None, user_id
284305
285306 for subscription in query :
286307 user_email = subscription .user .email
287-
288308 new_publications = Publication .objects .filter (
289309 geometry__intersects = subscription .region ,
290310 )
291-
292311 if not new_publications .exists ():
293312 continue
294313
295- unsubscribe_specific = f"{ BASE_URL } { reverse ('optimap:unsubscribe' )} ?search={ quote (subscription .search_term )} "
314+ unsubscribe_specific = (
315+ f"{ BASE_URL } { reverse ('optimap:unsubscribe' )} ?search="
316+ f"{ quote (subscription .search_term )} "
317+ )
296318 unsubscribe_all = f"{ BASE_URL } { reverse ('optimap:unsubscribe' )} ?all=true"
297319
298320 subject = f"📚 New Manuscripts Matching '{ subscription .search_term } '"
299- bullet_list = "\n " .join ([f"- { pub .title } " for pub in new_publications ])
321+ lines = []
322+ for pub in new_publications :
323+ link = _get_article_link (pub )
324+ lines .append (f"- { pub .title } : { link } " )
325+ bullet_list = "\n " .join (lines )
300326 content = f"""Dear { subscription .user .username } ,
301327Here are the latest manuscripts matching your subscription:
302328
@@ -311,17 +337,27 @@ def send_subscription_based_email(trigger_source='manual', sent_by=None, user_id
311337 email = EmailMessage (subject , content , settings .EMAIL_HOST_USER , [user_email ])
312338 email .send ()
313339 EmailLog .log_email (
314- user_email , subject , content , sent_by = sent_by , trigger_source = trigger_source , status = "success"
340+ user_email ,
341+ subject ,
342+ content ,
343+ sent_by = sent_by ,
344+ trigger_source = trigger_source ,
345+ status = "success"
315346 )
316347 time .sleep (settings .EMAIL_SEND_DELAY )
317348 except Exception as e :
318349 error_message = str (e )
319350 logger .error (f"Failed to send subscription email to { user_email } : { error_message } " )
320351 EmailLog .log_email (
321- user_email , subject , content , sent_by = sent_by , trigger_source = trigger_source , status = "failed" , error_message = error_message
352+ user_email ,
353+ subject ,
354+ content ,
355+ sent_by = sent_by ,
356+ trigger_source = trigger_source ,
357+ status = "failed" ,
358+ error_message = error_message
322359 )
323360
324- # ... (the rest of the file remains unchanged)
325361
326362def schedule_monthly_email_task (sent_by = None ):
327363 if not Schedule .objects .filter (func = 'publications.tasks.send_monthly_email' ).exists ():
0 commit comments