]>
git.ipfire.org Git - pbs.git/blob - src/buildservice/messages.py
4 import email
.mime
.multipart
10 import tornado
.template
15 from .constants
import TEMPLATESDIR
17 class Messages(base
.Object
):
19 self
.templates
= tornado
.template
.Loader(TEMPLATESDIR
)
22 messages
= self
.db
.query("SELECT * FROM messages \
23 WHERE sent_at IS NULL ORDER BY queued_at")
28 res
= self
.db
.get("SELECT COUNT(*) AS count FROM messages \
29 WHERE sent_at IS NULL")
33 def process_queue(self
):
35 Sends all emails in the queue
38 with self
.db
.transaction():
39 self
.__sendmail
(message
)
41 # Delete all old emails
42 with self
.db
.transaction():
46 self
.db
.execute("DELETE FROM messages WHERE sent_at <= NOW() - INTERVAL '24 hours'")
48 def send_to(self
, recipient
, message
, sender
=None, headers
={}):
50 if not isinstance(message
, email
.message
.Message
):
51 message
= email
.message_from_string(message
)
54 sender
= self
.backend
.settings
.get("email_from", "Pakfire Build Service <no-reply@ipfire.org>")
57 message
.add_header("From", sender
)
60 message
.add_header("To", recipient
)
62 # Sending this message now
63 message
.add_header("Date", email
.utils
.formatdate())
66 message
.add_header("X-Mailer", "Pakfire Build Service %s" % self
.backend
.version
)
69 for k
, v
in headers
.items():
70 message
.add_header(k
, v
)
73 self
.queue(message
.as_string())
75 def send_template(self
, recipient
, name
, sender
=None, headers
={}, **kwargs
):
76 # Get user (if we have one)
77 if isinstance(recipient
, users
.User
):
80 user
= self
.backend
.users
.find_maintainer(recipient
)
82 # Get the user's locale or use default
86 locale
= tornado
.locale
.get()
90 "baseurl" : self
.settings
.get("baseurl"),
91 "recipient" : recipient
,
96 "_" : locale
.translate
,
98 namespace
.update(kwargs
)
100 # Create a MIMEMultipart message.
101 message
= email
.mime
.multipart
.MIMEMultipart()
103 # Create an alternating multipart message to show HTML or text
104 alternative
= email
.mime
.multipart
.MIMEMultipart("alternative")
106 for fmt
, mimetype
in (("txt", "plain"), ("html", "html"), ("markdown", "html")):
108 t
= self
.templates
.load("%s.%s" % (name
, fmt
))
114 part
= t
.generate(**namespace
)
116 # Reset the rendered template when it could not be rendered
118 self
.templates
.reset()
122 part
= email
.message_from_string(part
)
124 # Extract the headers
125 for k
, v
in part
.items():
126 message
.add_header(k
, v
)
128 body
= part
.get_payload()
131 if fmt
== "markdown":
132 body
= markdown
.markdown(body
)
135 part
= email
.mime
.text
.MIMEText(body
, mimetype
, "utf-8")
137 # Attach the parts to the mime container
138 # According to RFC2046, the last part of a multipart message is preferred
139 alternative
.attach(part
)
141 # Add alternative section to outer message
142 message
.attach(alternative
)
145 self
.send_to(user
.email
.recipient
if user
else recipient
, message
, sender
=sender
, headers
=headers
)
147 def queue(self
, message
):
148 res
= self
.db
.get("INSERT INTO messages(message) VALUES(%s) RETURNING id", message
)
150 logging
.info("Message queued as %s", res
.id)
152 def __sendmail(self
, message
):
153 # Convert message from string
154 msg
= email
.message_from_string(message
.message
)
157 recipient
= msg
.get("To")
158 subject
= msg
.get("Subject")
160 logging
.info("Sending mail to %s: %s" % (recipient
, subject
))
162 # Run sendmail and the email in
163 p
= subprocess
.Popen(["/usr/lib/sendmail", "-t"], bufsize
=0, close_fds
=True,
164 stdin
=subprocess
.PIPE
, stdout
=subprocess
.PIPE
)
166 stdout
, stderr
= p
.communicate(msg
.as_string())
168 # Wait until sendmail has finished.
172 raise Exception, "Could not send mail: %s" % stderr
174 # Mark message as sent
175 self
.db
.execute("UPDATE messages SET sent_at = NOW() WHERE id = %s", message
.id)