~linuxgoose/bocpress

ref: e78dbbcef5121b4be449c26cca34d26410323fc6 bocpress/main/management/commands/mailexports.py -rw-r--r-- 4.1 KiB
e78dbbceJordan Robinson update wording on methodology page 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import io
import uuid
import zipfile
from datetime import datetime

from django.conf import settings
from django.core import mail
from django.core.management.base import BaseCommand
from django.utils import timezone

from main import models, util


def get_mail_connection():
    """Returns the default EmailBackend but instantiated with a custom host."""
    return mail.get_connection(
        "django.core.mail.backends.smtp.EmailBackend",
        host=settings.EMAIL_HOST_BROADCASTS,
    )


def get_unsubscribe_url(user):
    return util.get_protocol() + user.get_export_unsubscribe_url()


def get_email_body(user):
    """
    Returns the email body (which contains the post body) for the automated
    export email.
    """
    today = datetime.now().date().strftime("%B %d, %Y")
    body = f"""Greetings,

This is the {today} edition of your Mataroa blog export.

Please find your blog’s zip archive in markdown format attached.

---

Stop receiving exports:
{get_unsubscribe_url(user)}
"""
    return body


class Command(BaseCommand):
    help = "Generate zip account exports and email them to users."

    def handle(self, *args, **options):
        if timezone.now().day != 1:
            msg = "No action. Not the first day of the month."
            self.stdout.write(self.style.NOTICE(msg))
            return

        self.stdout.write(self.style.NOTICE("Processing email exports."))

        # gather all user posts for all users
        users = models.User.objects.filter(mail_export_on=True)
        for user in users:
            self.stdout.write(self.style.NOTICE(f"Processing user {user.username}."))

            user_posts = models.Post.objects.filter(owner=user)
            export_posts = []
            for p in user_posts:
                pub_date = p.published_at or p.created_at
                title = p.slug + ".md"
                body = (
                    f"# {p.title}\n\n"
                    f"> Published on {pub_date.strftime('%b %-d, %Y')}\n\n"
                    f"{p.body}\n"
                )
                export_posts.append((title, io.BytesIO(body.encode())))

            # write zip archive in /tmp/
            export_name = "export-markdown-" + str(uuid.uuid4())[:8]
            container_dir = f"{user.username}-mataroa-blog"
            zip_outfile = f"/tmp/{export_name}.zip"
            with zipfile.ZipFile(
                zip_outfile, "a", zipfile.ZIP_DEFLATED, False
            ) as export_archive:
                for file_name, data in export_posts:
                    export_archive.writestr(
                        export_name + f"/{container_dir}/" + file_name, data.getvalue()
                    )

            # reopen zipfile and load in memory
            with open(zip_outfile, "rb") as f:
                # create emails
                today = datetime.now().date().isoformat()
                email = mail.EmailMessage(
                    subject=f"Mataroa export {today}{user.username}.{settings.CANONICAL_HOST}",
                    body=get_email_body(user),
                    from_email=settings.DEFAULT_FROM_EMAIL,
                    to=[user.email],
                    headers={
                        "X-PM-Message-Stream": "exports",  # postmark-specific header
                        "List-Unsubscribe": get_unsubscribe_url(user),
                        "List-Unsubscribe-Post": "List-Unsubscribe=One-Click",
                    },
                    attachments=[(f"{export_name}.zip", f.read(), "application/zip")],
                )

            # sent out messages
            connection = get_mail_connection()
            connection.send_messages([email])
            self.stdout.write(self.style.SUCCESS(f"Export sent to {user.username}."))

            # log export record
            name = f"{export_name}.zip"
            record = models.ExportRecord.objects.create(name=name, user=user)
            self.stdout.write(
                self.style.SUCCESS(f"Logging export record for '{record.name}'.")
            )

        # log all users mailing is complete
        self.stdout.write(self.style.SUCCESS("Emailing all exports complete."))