Пример #1
0
def contact(request):
    captcha = None
    show_captcha = settings.REGISTRATION_CAPTCHA and not request.user.is_authenticated

    if request.method == "POST":
        form = ContactForm(request.POST)
        if show_captcha:
            captcha = CaptchaForm(request, form, request.POST)
        if not check_rate_limit("message", request):
            messages.error(
                request, _("Too many messages sent, please try again later."))
        elif (captcha is None or captcha.is_valid()) and form.is_valid():
            mail_admins_contact(
                request,
                "%(subject)s",
                CONTACT_TEMPLATE,
                form.cleaned_data,
                str(
                    Address(
                        display_name=form.cleaned_data["name"],
                        addr_spec=form.cleaned_data["email"],
                    )),
                settings.ADMINS_CONTACT,
            )
            return redirect("home")
    else:
        initial = get_initial_contact(request)
        if request.GET.get("t") in CONTACT_SUBJECTS:
            initial["subject"] = CONTACT_SUBJECTS[request.GET["t"]]
        form = ContactForm(initial=initial)
        if show_captcha:
            captcha = CaptchaForm(request)

    return render(
        request,
        "accounts/contact.html",
        {
            "form": form,
            "captcha_form": captcha,
            "title": _("Contact")
        },
    )
Пример #2
0
def sendMail(HTML_MESSAGE, display_name, username, domain, title):
    #Gmail mailbox details
    email_address = '*****@*****.**'  #gmail  mailbox
    email_password = '******'  #password to the mailbox
    #Define recipent
    to_address = (Address(display_name, username, domain), )
    #Create message with defined from/to  addresss, subject and text
    msg = create_email_message(
        from_address=email_address,
        to_address=to_address,
        subject=title,
        plaintext="Plain text version.",  #plain e-mail text
        html=HTML_MESSAGE)  #html e-mail text
    #Connect to Gmail mail server and send message
    with smtplib.SMTP('smtp.gmail.com', port=587) as smtp_server:
        smtp_server.ehlo()
        smtp_server.starttls()
        smtp_server.login(email_address, email_password)
        smtp_server.send_message(msg)
    print('Email sent successfully')
Пример #3
0
def draft_acceptance_email(proposal: Proposal):
    # Recipent
    username, domain = proposal.email.split("@")
    to_address = (Address(display_name=proposal.name,
                          username=username,
                          domain=domain), )
    return create_email_message(
        from_address=EMAIL_ADDRESS,
        to_address=to_address,
        subject="Chicago Python presents Spooky Lightning Talk Status",
        body=f"""Hi {proposal.name.split(" ")[0]},

Congratulations! Your submitted talk, {proposal.talk_title}, was accepted for Spooky Lightning Talks night on Wednesday, October 30th.

Please reply to this email to confirm you will be able to present your 5 minute talk.

I have secured equipment and will be recording each session for upload to the ChiPy YouTube channel.

Best Regards,
Aly Sivji""")
Пример #4
0
 def get_email_for_user(self, userid):
     tries = 2
     while tries:
         try:
             userinfo = self._get_userinfo(userid)
             app_log.debug('Userinfo for %s: %s', userid, userinfo)
             if not userinfo.get('email', '').strip():
                 raise Exception('No email configured for user %s', userid)
             return Address(display_name=userinfo.get('display_name', ''),
                            addr_spec=userinfo['email'])
         except InvalidGrantError as e:
             # log this error
             app_log.error("Invalid Grant Error %s", e)
             self._fetch_token()
             tries -= 1
         except TokenExpiredError as e:
             # our refreshtoken is gone :(
             app_log.error("Token Expired Error %s", e)
             self._fetch_token()
             tries -= 1
Пример #5
0
    def default_from_email(self) -> str:
        sender_name: str = self.default_mail_sender_name
        sender_address: Optional[str] = self.default_mail_sender_address

        if not sender_address:
            sender_address = settings.DEFAULT_FROM_EMAIL

            if not sender_address:
                raise ImproperlyConfigured(
                    "No sender email address has been set-up")

            sender_name, sender_address = parseaddr(sender_address)

        # Note: we only want to format the address in accordance to RFC 5322
        # but our job is not to sanitize the values. The sanitized value, encoding, etc.
        # will depend on the email backend being used.
        #
        # Refer to email.header.Header and django.core.mail.message.sanitize_address.
        value = str(Address(sender_name, addr_spec=sender_address))
        return value
Пример #6
0
def ses_relay_email(from_address, relay_address, subject, message_body,
                    attachments):
    relay_from_address, relay_from_display = generate_relay_From(from_address)
    formatted_from_address = str(
        Address(relay_from_display, addr_spec=relay_from_address))
    try:
        if attachments:
            response = ses_send_raw_email(formatted_from_address,
                                          relay_address.user.email, subject,
                                          message_body, attachments)
        else:
            response = ses_send_email(formatted_from_address,
                                      relay_address.user.email, subject,
                                      message_body)
        relay_address.num_forwarded += 1
        relay_address.last_used_at = datetime.now(timezone.utc)
        relay_address.save(update_fields=['num_forwarded', 'last_used_at'])
        return response
    except ClientError as e:
        logger.error('ses_client_error', extra=e.response['Error'])
        return HttpResponse("SES client error", status=400)
Пример #7
0
def send(body):
    # Gmail details
    email_address = os.environ.get("EMAIL_ADDRESSE")
    email_password = os.environ.get("PASSWORD")

    # Recipent
    to_address = (Address(display_name='naim',
                          username='******',
                          domain='gmail.com'), )

    if __name__ == '__main__':
        msg = create_email_message(from_address=email_address,
                                   to_address=to_address,
                                   subject='Hello World',
                                   body=body)

        with smtplib.SMTP('smtp.gmail.com', port=587) as smtp_server:
            smtp_server.ehlo()
            smtp_server.starttls()
            smtp_server.login(email_address, email_password)
            smtp_server.send_message(msg)
Пример #8
0
def generate_relay_From(original_from_address):
    relay_display_name, relay_from_address = parseaddr(
        settings.RELAY_FROM_ADDRESS)
    # RFC 2822 (https://tools.ietf.org/html/rfc2822#section-2.1.1)
    # says email header lines must not be more than 998 chars long.
    # Encoding display names to longer than 998 chars will add wrap
    # characters which are unsafe. (See https://bugs.python.org/issue39073)
    # So, truncate the original sender to 900 chars so we can add our
    # "[via Relay] <relayfrom>" and encode it all.
    if len(original_from_address) > 998:
        original_from_address = '%s ...' % original_from_address[:900]
    # line breaks in From: will encode to unsafe chars, so strip them.
    original_from_address = (original_from_address.replace(
        '\u2028', '').replace('\r', '').replace('\n', ''))

    display_name = Header('"%s [via Relay]"' % (original_from_address),
                          'UTF-8')
    formatted_from_address = str(
        Address(display_name.encode(maxlinelen=998),
                addr_spec=relay_from_address))
    return formatted_from_address
Пример #9
0
 def prep_mail(self, current_channel, what, username, cloak, message):
     current_time = time.strftime('%Y-%m-%d %I:%M:%S%p', time.localtime())
     msg = EmailMessage()
     msg['Subject'] = '[ALERT: IRC]'
     msg['From'] = sender
     msg['To'] = [
         Address(destination[email],
                 email.split('@')[0],
                 email.split('@')[1]) for email in destination
     ]
     # Not sure if this is actually needed since we're using add_alternative
     # https://docs.python.org/3/library/email.message.html#email.message.EmailMessage.add_alternative
     msg.set_content = ''
     if not jinja_found:
         self.email_template = NO_JINJA_EMAIL_TEMPLATE
         if current_channel is not None:
             self.email_template += f"        <b>Current Channel</b>: {current_channel}</br>\n"
         if what is not None:
             self.email_template += f"        <b>Type</b>: {what}</br>\n"
         if username is not None:
             self.email_template += f"        <b>Username</b>: {{username}}</br>\n"
         if cloak is not None:
             self.email_template += f"        <b>Cloak</b>: {{cloak}}</br>\n"
         if message is not None:
             self.email_template += f"        <b>Message</b>: {message}\n"
         self.email_template += "    <body>\n" + "</html>"
         msg.add_alternative(self.email_template, subtype='html')
     else:
         self.email_template = JINJA_EMAIL_TEMPLATE
         data = {
             'current_time': current_time,
             'current_channel': current_channel,
             'what': what,
             'username': username,
             'cloak': cloak,
             'message': message
         }
         prep_template = Template(self.email_template)
         msg.add_alternative(prep_template.render(data), subtype='html')
     self.mail_this(msg)
Пример #10
0
def send_email(config: EmailConfig,
               recipient_list,
               context,
               subject="",
               template_str=""):
    sender_name = config.sender_name or ""
    sender_address = config.sender_address

    from_email = str(Address(sender_name, addr_spec=sender_address))

    email_backend = EmailBackend(
        host=config.host,
        port=config.port,
        username=config.username,
        password=config.password,
        use_ssl=config.use_ssl,
        use_tls=config.use_tls,
        timeout=DEFAULT_EMAIL_TIMEOUT,
    )
    compiler = pybars.Compiler()
    template = compiler.compile(template_str)
    subject_template = compiler.compile(subject)
    helpers = {
        "format_address": format_address,
        "price": price,
        "format_datetime": format_datetime,
        "get_product_image_thumbnail": get_product_image_thumbnail,
        "compare": compare,
    }
    message = template(context, helpers=helpers)
    subject_message = subject_template(context, helpers)
    send_mail(
        subject_message,
        html2text.html2text(message),
        from_email,
        recipient_list,
        html_message=message,
        connection=email_backend,
    )
def draft_acceptance_email(proposal: Proposal):
    # Recipent
    username, domain = proposal.email.split("@")
    to_address = (Address(display_name=proposal.name,
                          username=username,
                          domain=domain), )
    return create_email_message(
        from_address=EMAIL_ADDRESS,
        to_address=to_address,
        subject="Python Powered Healthcare: Talk Accepted",
        body=f"""Hi {proposal.name.split(" ")[0]},

Congratulations! Your submitted talk, {proposal.talk_title}, was accepted for Python Powered Healthcare Night on Wednesday, February 19th.

Please reply to this email to confirm you will be able to attend and present your lightning talk.

Details about the event can be found on https://www.meetup.com/_ChiPy_/events/267264866/. Apologies if your talk description was shortened. Meetup has a character limit for the event description.

Please make sure to RSVP to ensure we have an accurate headcount.

Best Regards,
Aly Sivji""")
Пример #12
0
def sanitize_address(addr, encoding):
    """
    Format a pair of (name, address) or an email address string.
    """
    address = None
    if not isinstance(addr, tuple):
        addr = force_str(addr)
        try:
            token, rest = parser.get_mailbox(addr)
        except (HeaderParseError, ValueError, IndexError):
            raise ValueError('Invalid address "%s"' % addr)
        else:
            if rest:
                # The entire email address must be parsed.
                raise ValueError(
                    'Invalid adddress; only %s could be parsed from "%s"'
                    % (token, addr)
                )
            nm = token.display_name or ''
            localpart = token.local_part
            domain = token.domain or ''
    else:
        nm, address = addr
        localpart, domain = address.rsplit('@', 1)

    nm = Header(nm, encoding).encode()
    # Avoid UTF-8 encode, if it's possible.
    try:
        localpart.encode('ascii')
    except UnicodeEncodeError:
        localpart = Header(localpart, encoding).encode()
    try:
        domain.encode('ascii')
    except UnicodeEncodeError:
        domain = domain.encode('idna').decode('ascii')

    parsed_address = Address(nm, username=localpart, domain=domain)
    return str(parsed_address)
def send(temp, humid, last_time):
    msg = EmailMessage()
    msg['Subject'] = "Automated temperature alert"
    msg['From'] = Address("RPI-server", "humitemp", mail_user)
    msg['To'] = (mail_receiver)
    msg.set_content("""\
    <html>
      <head></head>
      <body>
        <p>temperature is {:0.1f}, optimally you want to stay under 26c<p/>
        <p>humidity is {:0.1f}, higher temps benefit from higher humidity<p/>
      </body>
    </html>
    """.format(temp, humid, config.CNF['last_time_called'], time.time(),
               (time.time() - config.CNF['last_time_called'])),
                    subtype='html')

    with smtplib.SMTP('smtp.gmail.com', 587) as smtp:
        smtp.ehlo()
        smtp.starttls()
        smtp.ehlo()
        smtp.login(user=mail_user, password=mail_password)
        smtp.send_message(msg)
Пример #14
0
    def validate_email(self, field):
        # Additional checks for the validity of the address
        try:
            Address(addr_spec=field.data)
        except ValueError:
            raise wtforms.validators.ValidationError(
                _("The email address isn't valid. Try again.")
            )

        # Check if the domain is valid
        domain = field.data.split("@")[-1]

        if domain in disposable_email_domains.blacklist:
            raise wtforms.validators.ValidationError(
                _(
                    "You can't use an email address from this domain. Use a "
                    "different email."
                )
            )

        # Check if this email address is already in use
        userid = self.user_service.find_userid_by_email(field.data)

        if userid and userid == self.user_id:
            raise wtforms.validators.ValidationError(
                _(
                    "This email address is already being used by this account. "
                    "Use a different email."
                )
            )
        if userid:
            raise wtforms.validators.ValidationError(
                _(
                    "This email address is already being used "
                    "by another account. Use a different email."
                )
            )
Пример #15
0
    def send(self):
        smtp = smtplib.SMTP_SSL(self.smtp_server, self.smtp_port)
        smtp.ehlo_or_helo_if_needed()
        smtp.login(self.username, self.password)

        msg = EmailMessage()
        msg['subject'] = self.subject
        msg['from'] = Address(self.display_name, addr_spec=self.username)
        msg['to'] = ', '.join(self.receivers)
        if self.cc:
            msg['cc'] = ','.join(self.cc)
        msg.add_alternative(self.content, subtype='html')
        for file in self.files:
            if not os.path.isfile(file):
                continue
            ctype, encoding = mimetypes.guess_type(file)
            if ctype is None or encoding is not None:
                # No guess could be made, or the file is encoded (compressed), so
                # use a generic bag-of-bits type.
                ctype = 'application/octet-stream'
            maintype, subtype = ctype.split('/', 1)
            with open(file, 'rb') as fp:
                msg.add_attachment(fp.read(),
                                   maintype=maintype,
                                   subtype=subtype,
                                   filename=file)
        for image in self.images:
            if not os.path.isfile(image):
                print('not found:', image)
                continue
            with open(image, 'rb') as fp:
                image_type = imghdr.what(image)
                msg.add_attachment(fp.read(), 'image', image_type, cid=image)
        smtp.send_message(msg)
        smtp.quit()
        return
Пример #16
0
def send(subject: str,  send_list: list, body: str, from_email: str = None) -> bool:
    """
    Function to send email with a gmail account to use this function you need activate
    the follow permission https://myaccount.google.com/lesssecureapps?pli=1 on gmail account.

    :param subject: email subject
    :param from_email: from email, default None
    :param send_list:  email or list of emails to send
    :param body: email body.
    :return:
    """

    # Make destination list
    destinations = []
    for email in send_list:
        info = email['email'].split('@')
        assert len(info) == 2, "Email incorrect verify list"
        add = Address(display_name=email['name'], username=info[0], domain=info[1])
        destinations.append(add)

    # Login account
    G_MAIL.login(G_EMAIL, PASSWORD)

    # CONFIGURING EMAIL
    MESSAGE = EmailMessage()
    MESSAGE['Subject'] = subject
    MESSAGE['From'] = G_EMAIL
    MESSAGE.set_content(body)
    MESSAGE['To'] = tuple(destinations) if len(destinations) > 1 else destinations[0]

    # Send message
    G_MAIL.send_message(MESSAGE)

    # Close connection
    G_MAIL.quit()
    return True
Пример #17
0
def test_extract_recipients_resent_message():
    message = EmailMessage()
    message["To"] = Address(username="******", domain="example.com")
    message["Cc"] = Address(username="******", domain="example.com")
    message["Bcc"] = Address(username="******", domain="example.com")

    message["Resent-Date"] = "Mon, 20 Nov 2017 21:04:27 -0000"
    message["Resent-To"] = Address(username="******", domain="example.com")
    message["Resent-Cc"] = Address(username="******", domain="example.com")
    message["Resent-Bcc"] = Address(username="******", domain="example.com")

    recipients = extract_recipients(message)

    assert message["Resent-To"] in recipients
    assert message["Resent-Cc"] in recipients
    assert message["Resent-Bcc"] in recipients
    assert message["To"] not in recipients
    assert message["Cc"] not in recipients
    assert message["Bcc"] not in recipients
Пример #18
0
    def email(self, recipients, subject=None, should_email=True, should_message_slack=True, should_attach_log=True, should_escape_chars=True):
        if not subject:
            assert isinstance(self.title, str) or self.pipeline is not None, "either title or pipeline must be specified when subject is missing"
            subject = self.title if self.title else self.pipeline.title

        smtp = {
            "host": Config.get("email.smtp.host", None),
            "port": Config.get("email.smtp.port", None),
            "user": Config.get("email.smtp.user", None),
            "pass": Config.get("email.smtp.pass", None)
        }
        sender = Address(Config.get("email.sender.name", "undefined"), addr_spec=Config.get("email.sender.address", "*****@*****.**"))

        # 0. Create attachment with complete log (including DEBUG statements)
        if should_attach_log is True:
            self.attachLog()

        attachments = []
        for m in self._messages["attachment"]:
            smb, file, unc = Filesystem.networkpath(m["text"])
            base_path = Filesystem.get_base_path(m["text"], self.pipeline.dir_base)
            relpath = os.path.relpath(m["text"], base_path) if base_path else None
            if m["text"].startswith(self.reportDir()):
                relpath = os.path.relpath(m["text"], self.reportDir())
            if not [a for a in attachments if a["unc"] == unc]:
                attachments.append({
                    "title": "{}{}".format(relpath, ("/" if os.path.isdir(m["text"]) else "")),
                    "smb": smb,
                    "file": file,
                    "unc": unc,
                    "severity": m["severity"]
                })

        # Determine overall status
        status = "INFO"
        for message_type in self._messages:
            for m in self._messages[message_type]:

                if m["severity"] == "SUCCESS" and status in ["INFO"]:
                    status = "SUCCESS"
                elif m["severity"] == "WARN" and status in ["INFO", "SUCCESS"]:
                    status = "WARN"
                elif m["severity"] == "ERROR":
                    status = "ERROR"

        try:
            assert isinstance(smtp, dict), "smtp must be a dict"
            assert isinstance(sender, Address), "sender must be a Address"
            assert isinstance(recipients, str) or isinstance(recipients, list) or isinstance(recipients, tuple), "recipients must be a str, list or tuple"
            assert isinstance(self.title, str) or self.pipeline and isinstance(self.pipeline.title, str), "title or pipeline.title must be a str"

            if isinstance(recipients, str):
                recipients = [recipients]
            elif isinstance(recipients, tuple):
                recipients = list(recipients)

            if status == "ERROR":
                for key in Config.get("administrators", default=[]):
                    if key not in recipients:
                        recipients.append(key)

            # when testing, only allow e-mail addresses defined in the ALLOWED_EMAIL_ADDRESSES_IN_TEST env var
            if Config.get("test"):
                subject = "[test] " + subject
                filtered_recipients = []
                for recipient in recipients:
                    if recipient in Config.get("email.allowed_email_addresses_in_test"):
                        filtered_recipients.append(recipient)
                recipients = filtered_recipients

            # 1. join lines with severity SUCCESS/INFO/WARN/ERROR
            markdown_text = []
            for m in self._messages["message"]:
                if should_escape_chars:
                    text = m['text'].replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
                else:
                    text = m['text']
                if m['preformatted'] is True:
                    markdown_text.append("<pre>{}</pre>".format(text))
                elif m['severity'] != 'DEBUG':
                    markdown_text.append(text)
            if attachments != [] or should_attach_log is True:
                markdown_text.append("\n----\n")
                markdown_text.append("\n# Lenker\n")
                markdown_text.append("\n<ul style=\"list-style: none;\">")

                # Pick icon and style for INFO-attachments
                attachment_styles = {
                    "DEBUG": {
                        "icon": "🗎",
                        "style": ""
                    },
                    "INFO": {
                        "icon": "🛈",
                        "style": ""
                    },
                    "SUCCESS": {
                        "icon": "😄",
                        "style": "background-color: #bfffbf;"
                    },
                    "WARN": {
                        "icon": "😟",
                        "style": "background-color: #ffffbf;"
                    },
                    "ERROR": {
                        "icon": "😭",
                        "style": "background-color: #ffbfbf;"
                    }
                }

                for attachment in attachments:
                    # UNC links seems to be preserved when viewed in Outlook.
                    # file: and smb: URIs are disallowed or removed.
                    # So these links will only work in Windows.
                    # If we need this to work cross-platform, we would have
                    # to map the network share paths to a web server so that
                    # the transfers go through http:. This could maybe be mapped
                    # using environment variables.
                    li = "<li>"
                    li += "<span style=\"vertical-align: middle; font-size: 200%;\">" + attachment_styles[attachment["severity"]]["icon"] + "</span> "
                    li += "<span style=\"vertical-align: middle; " + attachment_styles[attachment["severity"]]["style"] + "\">"
                    li += "<a href=\"file:///" + attachment["unc"] + "\">" + attachment["title"] + "</a> "
                    li += "<a href=\"" + attachment["smb"] + "\">" + self.img_string + "=\" alt=\"" + attachment["smb"] + "\"/>" + "</a> "
                    li += "</span>"
                    li += "</li>"
                    markdown_text.append(li)
                markdown_text.append("</ul>\n")
                label_string = ""
                for label in self.pipeline.labels:
                    label_string += "[{}] ".format(label)
                markdown_text.append("\n[{}] {} [{}] [status:{}]".format(self.pipeline.uid, label_string, self.pipeline.publication_format, status))
            markdown_text = "\n".join(markdown_text)

            # 2. parse string as Markdown and render as HTML
            if should_escape_chars:
                markdown_html = markdown.markdown(markdown_text, extensions=['markdown.extensions.fenced_code', 'markdown.extensions.codehilite'])
            else:
                markdown_html = markdown_text
            markdown_html = '''<!DOCTYPE html>
<html>
<head>
<meta charset=\"utf-8\"/>
<title>''' + subject.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;") + '''</title>
</head>
<body>
''' + markdown_html + '''
</body>
</html>
'''

            if not should_email:
                logging.info("[e-mail] Not sending email")
            else:
                # 3. build e-mail
                msg = EmailMessage()
                msg['Subject'] = re.sub(r"\s", " ", subject).strip()
                msg['From'] = sender
                msg['To'] = Report.emailStringsToAddresses(recipients)
                msg.set_content(markdown_text)
                msg.add_alternative(markdown_html, subtype="html")
                logging.info("[e-mail] E-mail with subject '{}' will be sent to: {}".format(msg['Subject'], ", ".join(recipients)))

                # 4. send e-mail
                if smtp["host"] and smtp["port"]:
                    smtp_server = "{}:{}".format(smtp["host"], smtp["port"])
                    logging.info("[e-mail] SMTP server: {}".format(smtp_server))
                    with smtplib.SMTP(smtp_server) as s:
                        s.ehlo()
                        # s.starttls()
                        if smtp["user"] and smtp["pass"]:
                            s.login(smtp["user"], smtp["pass"])
                        else:
                            logging.debug("[e-mail] user/pass not configured")
                        logging.debug("[e-mail] sending…")
                        s.send_message(msg)
                        logging.debug("[e-mail] sending complete.")
                else:
                    logging.warning("[e-mail] host/port not configured")

                temp_md_obj = tempfile.NamedTemporaryFile(suffix=".md")
                temp_html_obj = tempfile.NamedTemporaryFile(suffix=".html")
                with open(temp_md_obj.name, "w") as f:
                    f.write(markdown_text)
                    logging.debug("[e-mail] markdown: {}".format(temp_md_obj.name))
                with open(temp_html_obj.name, "w") as f:
                    f.write(markdown_html)
                    logging.debug("[e-mail] html: {}".format(temp_html_obj.name))
                if should_attach_log is True:
                    path_mail = os.path.join(self.reportDir(), "email.html")
                    shutil.copy(temp_html_obj.name, path_mail)
                    self.mailpath = Filesystem.networkpath(path_mail)
                else:
                    yesterday = datetime.now() - timedelta(1)
                    yesterday = str(yesterday.strftime("%Y-%m-%d"))
                    path_mail = os.path.join(self.pipeline.dir_reports, "logs", "dagsrapporter", yesterday, self.pipeline.uid + ".html")
                    shutil.copy(temp_html_obj.name, path_mail)
                    self.mailpath = Filesystem.networkpath(path_mail)

        except AssertionError as e:
            logging.error("[e-mail] " + str(e))
        if not should_message_slack:
            logging.warning("Not sending message to slack")
        else:
            # 5. send message to Slack
            slack_attachments = []
            for attachment in attachments:
                color = None
                if attachment["severity"] == "SUCCESS":
                    color = "good"
                elif attachment["severity"] == "WARN":
                    color = "warning"
                elif attachment["severity"] == "ERROR":
                    color = "danger"
                slack_attachments.append({
                    "title_link": attachment["smb"],
                    "title": attachment["title"],
                    "fallback": attachment["title"],
                    "color": color
                })
            Slack.slack(text=subject, attachments=slack_attachments)
Пример #19
0
from django.core.mail import send_mail
from django.template.loader import render_to_string
from django.test import override_settings, RequestFactory
from email.headerregistry import Address

organizers = Address("Outreachy Organizers", "organizers", "outreachy.org")


def send_template_mail(template,
                       context,
                       recipient_list,
                       request=None,
                       **kwargs):
    for recipient in recipient_list:
        context['recipient'] = recipient
        message = render_to_string(template,
                                   context,
                                   request=request,
                                   using='plaintext').strip()
        subject, body = message.split('\n', 1)
        kwargs.setdefault('from_email', organizers)
        send_mail(message=body.strip(),
                  subject=subject.strip(),
                  recipient_list=[recipient],
                  **kwargs)


def approval_status_changed(obj, request):
    if obj.approval_status == obj.PENDING:
        recipients = obj.get_approver_email_list()
    elif obj.approval_status == obj.APPROVED:
Пример #20
0
from django.core.mail import send_mail
from django.core.signing import TimestampSigner
from django.template.loader import render_to_string
from django.test import override_settings, RequestFactory
from email.headerregistry import Address

organizers = Address("Outreachy Organizers", "organizers", "outreachy.org")
applicant_help = Address("Outreachy Applicant Helpers", "applicant-help", "outreachy.org")

def send_template_mail(template, context, recipient_list, request=None, **kwargs):
    for recipient in recipient_list:
        context['recipient'] = recipient
        message = render_to_string(template, context, request=request, using='plaintext').strip()
        subject, body = message.split('\n', 1)
        if 'initial application' in subject:
            kwargs.setdefault('from_email', applicant_help)
        else:
            kwargs.setdefault('from_email', organizers)
        send_mail(message=body.strip(), subject=subject.strip(), recipient_list=[recipient], **kwargs)

def send_group_template_mail(template, context, recipient_list, request=None, **kwargs):
    context['recipient'] = recipient_list
    message = render_to_string(template, context, request=request, using='plaintext').strip()
    subject, body = message.split('\n', 1)
    kwargs.setdefault('from_email', organizers)
    send_mail(message=body.strip(), subject=subject.strip(), recipient_list=recipient_list, **kwargs)

def applicant_approval_status_changed(obj, request):
    if obj.approval_status == obj.PENDING:
        recipients = obj.get_approver_email_list()
    elif obj.approval_status == obj.APPROVED:
Пример #21
0
        text_results += f"    {size['name']:>11}: {dl_status[size['status']]}\n"
        html_results += f"      <tr><td>{size['name']}</td><td><font color=\"{link_color[size['status']]}\">" \
                        f"{dl_status[size['status']]}</font></td></tr>\n"
    html_results += "    </table>\n"
    text_results += "\n\n"

html_results += "  </body>\n</html>\n"

# Build email, and send
if config['mail']['send'] and got_new:
    envelope = EmailMessage()
    (from_name, from_user, from_domain) = config['mail']['from'].split(",")
    to_tuple = ()
    for recp in config['mail']['to'].split(":"):
        (to_name, to_user, to_domain) = recp.split(",")
        to_tuple = to_tuple + (Address(to_name, to_user, to_domain), )
    envelope['Subject'] = "New Images downloaded from Digital Blasphemy"
    envelope['From'] = Address(from_name, from_user, from_domain)
    envelope['To'] = to_tuple
    envelope.set_content(text_results)
    envelope.add_alternative(html_results, subtype="html")

    server = smtplib.SMTP(config['mail']['server'], config['mail']['port'])
    server.local_hostname = "db-downloader"
    server.ehlo_or_helo_if_needed()
    if "starttls" in server.esmtp_features:
        server.starttls()
    if config['mail']['auth_req']:
        try:
            server.login(config['mail']['user'], config['mail']['pass'])
        except smtplib.SMTPAuthenticationError as err:
Пример #22
0
def do_send_missedmessage_events_reply_in_zulip(user_profile: UserProfile,
                                                missed_messages: List[Dict[
                                                    str, Any]],
                                                message_count: int) -> None:
    """
    Send a reminder email to a user if she's missed some PMs by being offline.

    The email will have its reply to address set to a limited used email
    address that will send a Zulip message to the correct recipient. This
    allows the user to respond to missed PMs, huddles, and @-mentions directly
    from the email.

    `user_profile` is the user to send the reminder to
    `missed_messages` is a list of dictionaries to Message objects and other data
                      for a group of messages that share a recipient (and topic)
    """
    from zerver.context_processors import common_context

    # Disabled missedmessage emails internally
    if not user_profile.enable_offline_email_notifications:
        return

    recipients = {(msg["message"].recipient_id, msg["message"].topic_name())
                  for msg in missed_messages}
    if len(recipients) != 1:
        raise ValueError(
            f"All missed_messages must have the same recipient and topic {recipients!r}",
        )

    # This link is no longer a part of the email, but keeping the code in case
    # we find a clean way to add it back in the future
    unsubscribe_link = one_click_unsubscribe_link(user_profile,
                                                  "missed_messages")
    context = common_context(user_profile)
    context.update(
        name=user_profile.full_name,
        message_count=message_count,
        unsubscribe_link=unsubscribe_link,
        realm_name_in_notifications=user_profile.realm_name_in_notifications,
    )

    triggers = [message["trigger"] for message in missed_messages]
    unique_triggers = set(triggers)
    context.update(
        mention="mentioned" in unique_triggers
        or "wildcard_mentioned" in unique_triggers,
        stream_email_notify="stream_email_notify" in unique_triggers,
        mention_count=triggers.count("mentioned") +
        triggers.count("wildcard_mentioned"),
    )

    # If this setting (email mirroring integration) is enabled, only then
    # can users reply to email to send message to Zulip. Thus, one must
    # ensure to display warning in the template.
    if settings.EMAIL_GATEWAY_PATTERN:
        context.update(reply_to_zulip=True, )
    else:
        context.update(reply_to_zulip=False, )

    from zerver.lib.email_mirror import create_missed_message_address

    reply_to_address = create_missed_message_address(
        user_profile, missed_messages[0]["message"])
    if reply_to_address == FromAddress.NOREPLY:
        reply_to_name = ""
    else:
        reply_to_name = "Zulip"

    narrow_url = get_narrow_url(user_profile, missed_messages[0]["message"])
    context.update(narrow_url=narrow_url, )

    senders = list({m["message"].sender for m in missed_messages})
    if missed_messages[0]["message"].recipient.type == Recipient.HUDDLE:
        display_recipient = get_display_recipient(
            missed_messages[0]["message"].recipient)
        # Make sure that this is a list of strings, not a string.
        assert not isinstance(display_recipient, str)
        other_recipients = [
            r["full_name"] for r in display_recipient
            if r["id"] != user_profile.id
        ]
        context.update(group_pm=True)
        if len(other_recipients) == 2:
            huddle_display_name = " and ".join(other_recipients)
            context.update(huddle_display_name=huddle_display_name)
        elif len(other_recipients) == 3:
            huddle_display_name = (
                f"{other_recipients[0]}, {other_recipients[1]}, and {other_recipients[2]}"
            )
            context.update(huddle_display_name=huddle_display_name)
        else:
            huddle_display_name = "{}, and {} others".format(
                ", ".join(other_recipients[:2]),
                len(other_recipients) - 2)
            context.update(huddle_display_name=huddle_display_name)
    elif missed_messages[0]["message"].recipient.type == Recipient.PERSONAL:
        context.update(private_message=True)
    elif context["mention"] or context["stream_email_notify"]:
        # Keep only the senders who actually mentioned the user
        if context["mention"]:
            senders = list({
                m["message"].sender
                for m in missed_messages if m["trigger"] == "mentioned"
                or m["trigger"] == "wildcard_mentioned"
            })
        message = missed_messages[0]["message"]
        stream = Stream.objects.only("id",
                                     "name").get(id=message.recipient.type_id)
        stream_header = f"{stream.name} > {message.topic_name()}"
        context.update(stream_header=stream_header, )
    else:
        raise AssertionError("Invalid messages!")

    # If message content is disabled, then flush all information we pass to email.
    if not message_content_allowed_in_missedmessage_emails(user_profile):
        realm = user_profile.realm
        context.update(
            reply_to_zulip=False,
            messages=[],
            sender_str="",
            realm_str=realm.name,
            huddle_display_name="",
            show_message_content=False,
            message_content_disabled_by_user=not user_profile.
            message_content_in_email_notifications,
            message_content_disabled_by_realm=not realm.
            message_content_allowed_in_email_notifications,
        )
    else:
        context.update(
            messages=build_message_list(
                user=user_profile,
                messages=[m["message"] for m in missed_messages],
                stream_map={},
            ),
            sender_str=", ".join(sender.full_name for sender in senders),
            realm_str=user_profile.realm.name,
            show_message_content=True,
        )

    with override_language(user_profile.default_language):
        from_name: str = _("Zulip missed messages")
    from_address = FromAddress.NOREPLY
    if len(senders) == 1 and settings.SEND_MISSED_MESSAGE_EMAILS_AS_USER:
        # If this setting is enabled, you can reply to the Zulip
        # missed message emails directly back to the original sender.
        # However, one must ensure the Zulip server is in the SPF
        # record for the domain, or there will be spam/deliverability
        # problems.
        #
        # Also, this setting is not really compatible with
        # EMAIL_ADDRESS_VISIBILITY_ADMINS.
        sender = senders[0]
        from_name, from_address = (sender.full_name, sender.email)
        context.update(reply_to_zulip=False, )

    email_dict = {
        "template_prefix":
        "zerver/emails/missed_message",
        "to_user_ids": [user_profile.id],
        "from_name":
        from_name,
        "from_address":
        from_address,
        "reply_to_email":
        str(Address(display_name=reply_to_name, addr_spec=reply_to_address)),
        "context":
        context,
    }
    queue_json_publish("email_senders", email_dict)

    user_profile.last_reminder = timezone_now()
    user_profile.save(update_fields=["last_reminder"])
Пример #23
0
def _compute_recipient(user, email):
    # We want to try and use the user's name, then their username, and finally
    # nothing to display a "Friendly" name for the recipient.
    return str(
        Address(first([user.name, user.username], default=""),
                addr_spec=email))
Пример #24
0
def build_email(
    template_prefix: str,
    to_user_ids: Optional[List[int]] = None,
    to_emails: Optional[List[str]] = None,
    from_name: Optional[str] = None,
    from_address: Optional[str] = None,
    reply_to_email: Optional[str] = None,
    language: Optional[str] = None,
    context: Mapping[str, Any] = {},
    realm: Optional[Realm] = None,
) -> EmailMultiAlternatives:
    # Callers should pass exactly one of to_user_id and to_email.
    assert (to_user_ids is None) ^ (to_emails is None)
    if to_user_ids is not None:
        to_users = [get_user_profile_by_id(to_user_id) for to_user_id in to_user_ids]
        if realm is None:
            assert len({to_user.realm_id for to_user in to_users}) == 1
            realm = to_users[0].realm
        to_emails = [
            str(Address(display_name=to_user.full_name, addr_spec=to_user.delivery_email))
            for to_user in to_users
        ]

    extra_headers = {}
    if realm is not None:
        # formaddr is meant for formatting (display_name, email_address) pair for headers like "To",
        # but we can use its utility for formatting the List-Id header, as it follows the same format,
        # except having just a domain instead of an email address.
        extra_headers["List-Id"] = formataddr((realm.name, realm.host))

    context = {
        **context,
        "support_email": FromAddress.SUPPORT,
        "email_images_base_uri": settings.ROOT_DOMAIN_URI + "/static/images/emails",
        "physical_address": settings.PHYSICAL_ADDRESS,
    }

    def render_templates() -> Tuple[str, str, str]:
        email_subject = (
            loader.render_to_string(
                template_prefix + ".subject.txt", context=context, using="Jinja2_plaintext"
            )
            .strip()
            .replace("\n", "")
        )
        message = loader.render_to_string(
            template_prefix + ".txt", context=context, using="Jinja2_plaintext"
        )

        try:
            html_message = loader.render_to_string(template_prefix + ".html", context)
        except TemplateDoesNotExist:
            emails_dir = os.path.dirname(template_prefix)
            template = os.path.basename(template_prefix)
            compiled_template_prefix = os.path.join(emails_dir, "compiled", template)
            html_message = loader.render_to_string(compiled_template_prefix + ".html", context)
        return (html_message, message, email_subject)

    # The i18n story for emails is a bit complicated.  For emails
    # going to a single user, we want to use the language that user
    # has configured for their Zulip account.  For emails going to
    # multiple users or to email addresses without a known Zulip
    # account (E.g. invitations), we want to use the default language
    # configured for the Zulip organization.
    #
    # See our i18n documentation for some high-level details:
    # https://zulip.readthedocs.io/en/latest/translating/internationalization.html

    if not language and to_user_ids is not None:
        language = to_users[0].default_language
    if language:
        with override_language(language):
            # Make sure that we render the email using the target's native language
            (html_message, message, email_subject) = render_templates()
    else:
        (html_message, message, email_subject) = render_templates()
        logger.warning("Missing language for email template '%s'", template_prefix)

    if from_name is None:
        from_name = "Zulip"
    if from_address is None:
        from_address = FromAddress.NOREPLY
    if from_address == FromAddress.tokenized_no_reply_placeholder:
        from_address = FromAddress.tokenized_no_reply_address()
    if from_address == FromAddress.no_reply_placeholder:
        from_address = FromAddress.NOREPLY
    if from_address == FromAddress.support_placeholder:
        from_address = FromAddress.SUPPORT

    # Set the "From" that is displayed separately from the envelope-from.
    extra_headers["From"] = str(Address(display_name=from_name, addr_spec=from_address))
    # Check ASCII encoding length.  Amazon SES rejects emails with
    # From names longer than 320 characters (which appears to be a
    # misinterpretation of the RFC); in that case we drop the name
    # from the From line, under the theory that it's better to send
    # the email with a simplified From field than not.
    if len(sanitize_address(extra_headers["From"], "utf-8")) > 320:
        extra_headers["From"] = str(Address(addr_spec=from_address))

    # If we have an unsubscribe link for this email, configure it for
    # "Unsubscribe" buttons in email clients via the List-Unsubscribe header.
    #
    # Note that Microsoft ignores URLs in List-Unsubscribe headers, as
    # they only support the alternative `mailto:` format, which we
    # have not implemented.
    if "unsubscribe_link" in context:
        extra_headers["List-Unsubscribe"] = f"<{context['unsubscribe_link']}>"
        extra_headers["List-Unsubscribe-Post"] = "List-Unsubscribe=One-Click"

    reply_to = None
    if reply_to_email is not None:
        reply_to = [reply_to_email]
    # Remove the from_name in the reply-to for noreply emails, so that users
    # see "noreply@..." rather than "Zulip" or whatever the from_name is
    # when they reply in their email client.
    elif from_address == FromAddress.NOREPLY:
        reply_to = [FromAddress.NOREPLY]

    envelope_from = FromAddress.NOREPLY
    mail = EmailMultiAlternatives(
        email_subject, message, envelope_from, to_emails, reply_to=reply_to, headers=extra_headers
    )
    if html_message is not None:
        mail.attach_alternative(html_message, "text/html")
    return mail
Пример #25
0
def test_compile_text_undecodable_quote() -> None:
    from_addr = Address("Joe Q. Sender", addr_spec="*****@*****.**")
    to_addrs = (
        Address(addr_spec="*****@*****.**"),
        Address("Jane Q. Recipient", addr_spec="*****@*****.**"),
    )
    draft = DraftMessage(
        from_addr=from_addr,
        to_addrs=to_addrs,
        subject="This is a test e-mail.",
    )
    draft.addtext("This is a quote:\n")
    draft.addblobquote(
        b"\xD0is is i\xF1 L\xE1tin\xB9.\n",
        "utf-8",
        "latin1.txt",
    )
    assert email2dict(draft.compile()) == {
        "unixfrom": None,
        "headers": {
            "subject": "This is a test e-mail.",
            "from": [addr2dict(from_addr)],
            "to": list(map(addr2dict, to_addrs)),
            "user-agent": [USER_AGENT],
            "content-type": {
                "content_type": "multipart/mixed",
                "params": {},
            },
        },
        "preamble": None,
        "content": [
            {
                "unixfrom": None,
                "headers": {
                    "content-type": {
                        "content_type": "text/plain",
                        "params": {},
                    },
                },
                "preamble": None,
                "content": "This is a quote:\n",
                "epilogue": None,
            },
            {
                "unixfrom": None,
                "headers": {
                    "content-type": {
                        "content_type": "application/octet-stream",
                        "params": {},
                    },
                    "content-disposition": {
                        "disposition": "inline",
                        "params": {"filename": "latin1.txt"},
                    },
                },
                "preamble": None,
                "content": b"\xD0is is i\xF1 L\xE1tin\xB9.\n",
                "epilogue": None,
            },
        ],
        "epilogue": None,
    }
Пример #26
0
    def emailPlainText(subject, message, recipients, should_email=True):
        assert isinstance(subject, str), "subject must be a str, was: {}".format(type(subject))
        assert isinstance(message, str), "message must be a str, was: {}".format(type(message))

        if recipients is None:
            logging.info("No recipients given, e-mail won't be sent: '" + subject + "'")
            return

        assert isinstance(recipients, str) or isinstance(recipients, list), (
            "recipients must be a str or list, was: {}".format(type(recipients))
        )

        smtp = {
            "host": Config.get("email.smtp.host", None),
            "port": Config.get("email.smtp.port", None),
            "user": Config.get("email.smtp.user", None),
            "pass": Config.get("email.smtp.pass", None)
        }
        sender = Address(Config.get("email.sender.name", "undefined"), addr_spec=Config.get("email.sender.address", "*****@*****.**"))

        if isinstance(recipients, str):
            recipients = [recipients]

        if not should_email:
            logging.info("[e-mail] Not sending plain text email")
        else:
            if Config.get("test"):
                subject = "[test] " + subject
                filtered_recipients = []
                for recipient in recipients:
                    if recipient in Config.get("email.allowed_email_addresses_in_test"):
                        filtered_recipients.append(recipient)
                recipients = filtered_recipients

            # 1. build e-mail
            msg = EmailMessage()
            msg['Subject'] = subject
            msg['From'] = sender
            msg['To'] = Report.emailStringsToAddresses(recipients)
            msg.set_content(message)

            # 2. send e-mail
            if not msg["To"]:
                logging.warning("[e-mail] Email with subject \"{}\" has no recipients".format(subject))
            else:
                logging.info("[e-mail] Sending email with subject \"{}\" to: {}".format(subject, ", ".join(recipients)))
                if isinstance(smtp["host"], str) and isinstance(smtp["port"], str):
                    with smtplib.SMTP(smtp["host"] + ":" + smtp["port"]) as s:
                        s.ehlo()
                        # s.starttls()
                        if smtp["user"] and smtp["pass"]:
                            s.login(smtp["user"], smtp["pass"])
                        else:
                            logging.debug("[e-mail] user/pass not configured")
                        logging.debug("[e-mail] sending…")
                        s.send_message(msg)
                        logging.debug("[e-mail] sending complete.")
                else:
                    logging.warning("[e-mail] host/port not configured")

        Slack.slack(text=subject, attachments=None)
Пример #27
0
from django.core.mail import send_mail
from django.core.signing import TimestampSigner
from django.db import transaction
from django.template import TemplateDoesNotExist
from django.template.loader import get_template
from django.test import override_settings, RequestFactory
from email.headerregistry import Address
import logging

logger = logging.getLogger(__name__)

organizers = Address("Outreachy Organizers", "organizers", "outreachy.org")
applicant_help = Address("Outreachy Applicant Helpers", "applicant-help",
                         "outreachy.org")
mentors_mailing_list = Address("Outreachy mentors list", "mentors",
                               "lists.outreachy.org")


def send_template_mail(template_name,
                       context,
                       recipient_list,
                       request=None,
                       **kwargs):
    # Only load the template once, no matter how many messages we're sending.
    template = get_template(template_name, using='plaintext')
    for recipient in recipient_list:
        # Templates used with this function expect the 'recipient' context
        # variable to contain a single address, not a list, so override
        # send_group_template_mail's default.
        context['recipient'] = recipient
        send_group_template_mail(template, context, [recipient], request,
Пример #28
0
from email.headerregistry import Address
from email.message import EmailMessage
import os
import smtplib
import sys

# Gmail details
email_address = "*****@*****.**"
email_password = "******"

# Recipent
to_address = (
	Address(username='******', domain='hotmail.com'),
	Address(username='******', domain='lohjanpallo.fi')
)


def create_email_message(from_address, to_address, subject, body):
    msg = EmailMessage()
    msg['From'] = from_address
    msg['To'] = to_address
    msg['Subject'] = subject
    msg.set_content(body)
    return msg

if sys.argv[1] == '0':
	title='Sähkökatko on ohi'
	text='Sähkökatko ohi kuplahallissa!'
else:
	title='Sähkökatko'
	text='Sähkökatko kuplahallissa!'
Пример #29
0
 def test_find_email_addresses_single_header_finds_one_address(self):
     text = """From: John Doe <*****@*****.**>"""
     addrs = find_email_addresses(text, ["from"])
     expected = [Address(display_name="John Doe",
                         username="******", domain="machine.example")]
     self.assertEqual(expected, addrs)
Пример #30
0
from email.headerregistry import Address, Group
from typing import List, Union
import pytest
from mailbits import parse_addresses


@pytest.mark.parametrize(
    "s,addresses",
    [
        ("", []),
        (
            "Some User <*****@*****.**>",
            [Address("Some User", addr_spec="*****@*****.**")],
        ),
        (
            "Some User <*****@*****.**>, [email protected]",
            [
                Address("Some User", addr_spec="*****@*****.**"),
                Address(addr_spec="*****@*****.**"),
            ],
        ),
        (
            (
                "friends: [email protected], [email protected];,"
                " enemies:[email protected], [email protected];"
            ),
            [
                Group(
                    "friends",
                    (
                        Address(addr_spec="*****@*****.**"),