diff --git a/django/shortcuts/__init__.py b/django/shortcuts/__init__.py
index 9f97cae..db31ee4 100644
--- a/django/shortcuts/__init__.py
+++ b/django/shortcuts/__init__.py
@@ -4,12 +4,14 @@ of MVC. In other words, these functions/classes introduce controlled coupling
 for convenience's sake.
 """
 
-from django.template import loader, RequestContext
+from django.template import loader, Context, RequestContext
+from django.template.loader_tags import BlockNode, ExtendsNode
 from django.http import HttpResponse, Http404
 from django.http import HttpResponseRedirect, HttpResponsePermanentRedirect
 from django.db.models.manager import Manager
 from django.db.models.query import QuerySet
-from django.core import urlresolvers
+from django.core import urlresolvers, mail
+from django.utils.html import strip_tags
 
 def render_to_response(*args, **kwargs):
     """
@@ -128,3 +130,124 @@ def get_list_or_404(klass, *args, **kwargs):
         raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
     return obj_list
 
+
+def _get_node(template, name):
+    """
+    Get a named node from a template.
+    Returns `None` if a node with the given name does not exist.
+    """
+    for node in template:
+        if isinstance(node, BlockNode) and node.name == name:
+            return node
+        elif isinstance(node, ExtendsNode):
+            return _get_node(node.nodelist, name)
+    return None
+
+
+def _render_node(template, node_name, context):
+    """
+    Shortcut to render a named node from a template, using the given context.
+    Returns `None` if a node with the given name does not exist.
+
+    Note that leading and trailing whitespace is stripped from the output.
+    """
+    node = _get_node(template, node_name)
+    if node is None:
+        return None
+    return node.render(context).strip()
+
+
+def _create_message(subject, plain, html,
+                    from_email, recipient_list, connection):
+    """
+    Return an EmailMessage instance, containing either a plaintext
+    representation, or a multipart html/plaintext representation.
+    """
+    if html:
+        message = mail.EmailMultiAlternatives(
+            subject or '',
+            plain or '',
+            from_email,
+            recipient_list,
+            connection=connection,
+        )
+        message.attach_alternative(html, 'text/html')
+
+    else:
+        message = mail.EmailMessage(
+            subject or '',
+            plain or '',
+            from_email,
+            recipient_list,
+            connection=connection,
+        )
+
+    return message
+
+
+def _render_mail(template_name, from_email, recipient_list,
+                 dictionary=None, context_instance=None,
+                 fail_silently=False,
+                 auth_user=None, auth_password=None,
+                 connection=None):
+    """
+    Returns an EmailMessage instance, rendering the subject and body of the
+    email from a template.
+
+    The template should contain a block named 'subject',
+    and either/both of a 'plain' and/or 'html' block.
+
+    If only the 'plain' block exists, a plaintext email will be sent.
+
+    If only the 'html' block exists, the plaintext component will be
+      automatically generated from the html, and a multipart email will be sent.
+
+    If both the 'plain' and 'html' blocks exist, a multipart email will be sent.
+
+    Required arguments:
+    `template_name` - The template that should be used to render the email.
+    `from_email` - The sender's email address.
+    `recipient_list` - A list of reciepient's email addresses.
+
+    Optional arguments:
+    `dictionary` - The context dictionary used to render the template.
+                   By default, this is an empty dictionary.
+    `context_instance` - The Context instance used to render the template.
+                         By default, the template will be rendered with a
+                         Context instance (filled with values from dictionary).
+    `fail_silently` - As in Django's send_mail.
+    `auth_user`     - As in Django's send_mail.
+    `auth_password` - As in Django's send_mail.
+    `connection`    - As in Django's send_mail.
+    """
+    if dictionary is None:
+        dictionary = {}
+    if context_instance is None:
+        context_instance = Context()
+    if connection is None:
+        connection = mail.get_connection(username=auth_user,
+                                         password=auth_password,
+                                         fail_silently=fail_silently)
+
+    context_instance.update(dictionary)
+    template = loader.get_template(template_name)
+
+    subject = _render_node(template, 'subject', context_instance)
+    plain = _render_node(template, 'plain', context_instance)
+    html = _render_node(template, 'html', context_instance)
+
+    # Always strip newlines from subject
+    if subject is not None:
+        subject = ' '.join(subject.splitlines())
+
+    # Auto-generate plaintext if no 'plain' block exists
+    if plain is None and not html is None:
+        plain = strip_tags(html)
+
+    message = _create_message(subject, plain, html,
+                              from_email, recipient_list, connection)
+    return message
+
+
+def send_templated_mail(*args, **kwargs):
+    return _render_mail(*args, **kwargs).send()
