| 133 | |
| 134 | def _get_node(template, name): |
| 135 | """ |
| 136 | Get a named node from a template. |
| 137 | Returns `None` if a node with the given name does not exist. |
| 138 | """ |
| 139 | for node in template: |
| 140 | if isinstance(node, BlockNode) and node.name == name: |
| 141 | return node |
| 142 | elif isinstance(node, ExtendsNode): |
| 143 | return _get_node(node.nodelist, name) |
| 144 | return None |
| 145 | |
| 146 | |
| 147 | def _render_node(template, node_name, context): |
| 148 | """ |
| 149 | Shortcut to render a named node from a template, using the given context. |
| 150 | Returns `None` if a node with the given name does not exist. |
| 151 | |
| 152 | Note that leading and trailing whitespace is stripped from the output. |
| 153 | """ |
| 154 | node = _get_node(template, node_name) |
| 155 | if node is None: |
| 156 | return None |
| 157 | return node.render(context).strip() |
| 158 | |
| 159 | |
| 160 | def _create_message(subject, plain, html, |
| 161 | from_email, recipient_list, connection): |
| 162 | """ |
| 163 | Return an EmailMessage instance, containing either a plaintext |
| 164 | representation, or a multipart html/plaintext representation. |
| 165 | """ |
| 166 | if html: |
| 167 | message = mail.EmailMultiAlternatives( |
| 168 | subject or '', |
| 169 | plain or '', |
| 170 | from_email, |
| 171 | recipient_list, |
| 172 | connection=connection, |
| 173 | ) |
| 174 | message.attach_alternative(html, 'text/html') |
| 175 | |
| 176 | else: |
| 177 | message = mail.EmailMessage( |
| 178 | subject or '', |
| 179 | plain or '', |
| 180 | from_email, |
| 181 | recipient_list, |
| 182 | connection=connection, |
| 183 | ) |
| 184 | |
| 185 | return message |
| 186 | |
| 187 | |
| 188 | def _render_mail(template_name, from_email, recipient_list, |
| 189 | dictionary=None, context_instance=None, |
| 190 | fail_silently=False, |
| 191 | auth_user=None, auth_password=None, |
| 192 | connection=None): |
| 193 | """ |
| 194 | Returns an EmailMessage instance, rendering the subject and body of the |
| 195 | email from a template. |
| 196 | |
| 197 | The template should contain a block named 'subject', |
| 198 | and either/both of a 'plain' and/or 'html' block. |
| 199 | |
| 200 | If only the 'plain' block exists, a plaintext email will be sent. |
| 201 | |
| 202 | If only the 'html' block exists, the plaintext component will be |
| 203 | automatically generated from the html, and a multipart email will be sent. |
| 204 | |
| 205 | If both the 'plain' and 'html' blocks exist, a multipart email will be sent. |
| 206 | |
| 207 | Required arguments: |
| 208 | `template_name` - The template that should be used to render the email. |
| 209 | `from_email` - The sender's email address. |
| 210 | `recipient_list` - A list of reciepient's email addresses. |
| 211 | |
| 212 | Optional arguments: |
| 213 | `dictionary` - The context dictionary used to render the template. |
| 214 | By default, this is an empty dictionary. |
| 215 | `context_instance` - The Context instance used to render the template. |
| 216 | By default, the template will be rendered with a |
| 217 | Context instance (filled with values from dictionary). |
| 218 | `fail_silently` - As in Django's send_mail. |
| 219 | `auth_user` - As in Django's send_mail. |
| 220 | `auth_password` - As in Django's send_mail. |
| 221 | `connection` - As in Django's send_mail. |
| 222 | """ |
| 223 | if dictionary is None: |
| 224 | dictionary = {} |
| 225 | if context_instance is None: |
| 226 | context_instance = Context() |
| 227 | if connection is None: |
| 228 | connection = mail.get_connection(username=auth_user, |
| 229 | password=auth_password, |
| 230 | fail_silently=fail_silently) |
| 231 | |
| 232 | context_instance.update(dictionary) |
| 233 | template = loader.get_template(template_name) |
| 234 | |
| 235 | subject = _render_node(template, 'subject', context_instance) |
| 236 | plain = _render_node(template, 'plain', context_instance) |
| 237 | html = _render_node(template, 'html', context_instance) |
| 238 | |
| 239 | # Always strip newlines from subject |
| 240 | if subject is not None: |
| 241 | subject = ' '.join(subject.splitlines()) |
| 242 | |
| 243 | # Auto-generate plaintext if no 'plain' block exists |
| 244 | if plain is None and not html is None: |
| 245 | plain = strip_tags(html) |
| 246 | |
| 247 | message = _create_message(subject, plain, html, |
| 248 | from_email, recipient_list, connection) |
| 249 | return message |
| 250 | |
| 251 | |
| 252 | def send_templated_mail(*args, **kwargs): |
| 253 | return _render_mail(*args, **kwargs).send() |