Coverage for src/couchers/email/__init__.py: 100%

24 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-07-22 17:19 +0000

1import logging 

2from html import escape 

3from pathlib import Path 

4 

5import yaml 

6from jinja2 import Environment, FileSystemLoader 

7 

8from couchers.config import config 

9from couchers.jobs.enqueue import queue_job 

10from proto.internal import jobs_pb2 

11 

12logger = logging.getLogger(__name__) 

13 

14loader = FileSystemLoader(Path(__file__).parent / ".." / ".." / ".." / "templates") 

15env = Environment(loader=loader, trim_blocks=True) 

16 

17 

18def _queue_email(sender_name, sender_email, recipient, subject, plain, html, list_unsubscribe_header, source_data): 

19 payload = jobs_pb2.SendEmailPayload( 

20 sender_name=sender_name, 

21 sender_email=sender_email, 

22 recipient=recipient, 

23 subject=subject, 

24 plain=plain, 

25 html=html, 

26 list_unsubscribe_header=list_unsubscribe_header, 

27 source_data=source_data, 

28 ) 

29 queue_job( 

30 job_type="send_email", 

31 payload=payload, 

32 ) 

33 

34 

35def queue_email( 

36 sender_name, sender_email, recipient, subject, plain, html, list_unsubscribe_header=None, source_data=None 

37): 

38 """ 

39 This indirection is so that this can be easily mocked. Not sure how to do it better :( 

40 """ 

41 _queue_email( 

42 sender_name=sender_name, 

43 sender_email=sender_email, 

44 recipient=recipient, 

45 subject=subject, 

46 plain=plain, 

47 html=html, 

48 list_unsubscribe_header=list_unsubscribe_header, 

49 source_data=source_data, 

50 ) 

51 

52 

53def enqueue_system_email(recipient, template_name, template_args): 

54 source, _, _ = loader.get_source(env, f"system/{template_name}.md") 

55 _, frontmatter_source, text_source = source.split("---", 2) 

56 

57 rendered_frontmatter = env.from_string(frontmatter_source).render(**template_args, plain=True, html=False) 

58 frontmatter = yaml.load(rendered_frontmatter, Loader=yaml.FullLoader) 

59 

60 plain = env.from_string(text_source).render({**template_args, "frontmatter": frontmatter}, plain=True, html=False) 

61 

62 # chatwoot won't show plaintext correctly, so wrap it in some HTML 

63 html = f"<html><body><pre>{escape(plain)}</pre></body></html>" 

64 

65 queue_email( 

66 config["NOTIFICATION_EMAIL_SENDER"], 

67 config["NOTIFICATION_EMAIL_ADDRESS"], 

68 recipient, 

69 config["NOTIFICATION_EMAIL_PREFIX"] + frontmatter["subject"], 

70 plain, 

71 html, 

72 source_data=template_name, 

73 )