Fastapi mail system sending mails(individual, bulk) attachments(individual, bulk)

Overview

Fastapi-mail

The fastapi-mail simple lightweight mail system, sending emails and attachments(individual && bulk)

MIT licensed GitHub stars GitHub forks GitHub issues Downloads

🔨 Installation

 $ pip install fastapi-mail

Documentation: FastApi-MAIL

The key feature are:

  • sending emails with either with FastApi or using asyncio module
  • sending emails using FastApi backroung task managment
  • sending files either from form-data or files from server
  • Using Jinja2 HTML Templates
  • email utils (utility allows you to check temporary email addresses, you can block any email or domain)
  • email utils has two avalibale class DefaultChecker and WhoIsXmlApi
  • Unittests using FastapiMail

More information on Getting-Started

Guide

from fastapi import FastAPI, BackgroundTasks, UploadFile, File, Form
from starlette.responses import JSONResponse
from starlette.requests import Request
from fastapi_mail import FastMail, MessageSchema,ConnectionConfig
from pydantic import BaseModel, EmailStr
from typing import List



class EmailSchema(BaseModel):
    email: List[EmailStr]


conf = ConnectionConfig(
    MAIL_USERNAME = "YourUsername",
    MAIL_PASSWORD = "strong_password",
    MAIL_FROM = "[email protected]",
    MAIL_PORT = 587,
    MAIL_SERVER = "your mail server",
    MAIL_TLS = True,
    MAIL_SSL = False,
    USE_CREDENTIALS = True
)

app = FastAPI()


template = """
<p>Thanks for using Fastapi-mail</p> 
"""


@app.post("/email")
async def simple_send(email: EmailSchema) -> JSONResponse:

    message = MessageSchema(
        subject="Fastapi-Mail module",
        recipients=email.dict().get("email"),  # List of recipients, as many as you can pass 
        body=html,
        subtype="html"
        )

    fm = FastMail(conf)
    await fm.send_message(message)
    return JSONResponse(status_code=200, content={"message": "email has been sent"})     

List of Examples

for more examples of using fastapi-mail please check example section

Contributing

Fell free to open issue and send pull request.

Contributors

Thanks goes to these wonderful people ( 🚧 ):


Sabuhi Shukurov

💬 👀 🚧

Tural Muradov

📖 👀 🔧

Hasan Aliyev

📖 🚧 👀

Ashwani

🚧

Leon Xu

🚧

Gabriel Oliveira

📖 🚧

Onothoja Marho

📖 🚧 🔧

Tim Kiely

🚧

Dmitriy Solodkiy

🚧

Peter Boers

🚧

This project follows the all-contributors specification. Contributions of any kind are welcome!

Before you start please read CONTRIBUTING

LICENSE

MIT

Comments
  • send_message as background task is not working

    send_message as background task is not working

    Mails are not going out in background.

    We have backgrounds tasks working well in other endpoints. Any idea of what could be the issue?

    We tried without a template (exactly like your example) and it does not work either.

    class SigninEmailSchema(BaseModel):
        recipient: EmailStr
        a: str
        b: str
    
    
    @router.post('/email/signin')
    async def send_signin_email(
            bg: BackgroundTasks,
            contents: SigninEmailSchema,
        ) -> JSONResponse:
    
        message = MessageSchema(
            subject = ' subject ',
            recipients = [contents.recipient],
            template_body = {
                'a': contents.a,
                'b': contents.b,
            },
        )
    
        fm = FastMail(conf)
    
        #await fm.send_message(message, template_name='signin.html') # WORKS
        bg.add_task(fm.send_message, message, template_name='signin.html') # DOES NOT WORK
    
        return JSONResponse(
            status_code=200,
            content = {'message': 'email was sent'},
    )
    
    opened by pepegc 21
  • remove TEMPLATE_FOLDER validation because Pydantic DirectoryPath already does that…

    remove TEMPLATE_FOLDER validation because Pydantic DirectoryPath already does that…

    fastapi-mail ConnectionConfig does not need to check for a valid TEMPLATE_FOLDER value since pydantic's DirectoryPath already does that: https://pydantic-docs.helpmanual.io/usage/types/#pydantic-types

    opened by andredias 16
  • fastapi 0.70.0

    fastapi 0.70.0

    fastapi 0.70.0

    Because fastapi-mail (1.0.1) depends on fastapi (>=0.68.1,<0.69.0) and no versions of fastapi-mail match >1.0.1,<2.0.0, fastapi-mail (>=1.0.1,<2.0.0) requires fastapi (>=0.68.1,<0.69.0). So, because hashjump co api depends on both fastapi (^0.70.0) and fastapi-mail (^1.0.1), version solving failed.

    opened by clerkzhang 9
  • [Question] Gmail

    [Question] Gmail "MAIL_USERNAME" ConnectionConfig

    How do i use gmail alias with "MAIL_USERNAME"? Using gmail, i keep getting bad credential error.

    What i'm trying to achieve is SportJom [email protected]

    but that was not possible if my "MAIL_USERNAME" is not the email address.

    For "MAIL_USERNAME" I have to use my full email address as the username. Is this just gmail issue?

    opened by ihsanmohamad 9
  • path_traversal with venv

    path_traversal with venv

    Hello!

    I'm using poetry and got an issue with TEMPLATE_FOLDER option with exception TemplateFolderDoesNotExist because it not pass path_traversal check.

    After debug I found out that:

    • base = Path(__file__).parent.parent inside path_traversal equals to PosixPath('/Users/netstuff/Sites/mailout/api/.venv/lib/python3.9/site-packages')
    • passed to TEMPLATE_FOLDER path equals to PosixPath('/Users/netstuff/Sites/mailout/api/src/mailout/templates/mail')

    What can I do with it? Thank you.

    opened by netstuff 8
  • Feature adding reply to support

    Feature adding reply to support

    Please let me know what changes you'd like. I went back to RFC 2822 to check what I've done is correct, and I've tested with this version as a local package in my own project. It seems to work correctly but I would appreciate your advice.

    I have run the tests but did not create the SMTP endpoint. I'm confident of my changes, though.

    opened by jdvalentine 8
  • Jinja2 templates not getting populated with body

    Jinja2 templates not getting populated with body

    I'm trying to send an HTML rendered email with Jinja2 templates, but no context is being send.

    Here's an example of the message I'm sending...

    message = MessageSchema(
        subject="Grove Password Reset",
        recipients=[form.email],
        body={"email": email, "other": "some random string"},
        subtype="html",
    )
    
    fast_mail = FastMail(settings.EMAIL_CONFIG)
    
    background_tasks.add_task(fast_mail.send_message, message, template_name="template.html")
    

    The email is sent correctly, and the template shows up as a rendered HTML email, but none of the information from the body parameter gets rendered.

    opened by fletcheaston 7
  • Send local attachments

    Send local attachments

    Hello, How can i send files from local directory? when i give a "./app/files/file.pdf" path, I receive this error:

    AttributeError: 'bytes' object has no attribute 'read'

    or

    attachments field type incorrect, must be UploadFile or path

    opened by UtopiaBe 7
  • coroutine was never awaited error

    coroutine was never awaited error

    Hi, I created a function like this

    async def email_simple_send() -> JSONResponse:
        email = EmailSchema(email=['[email protected]'])
        html = """<p>Hi this test mail, thanks for using Fastapi-mail</p> """
        message = MessageSchema(
            subject="Test",
            recipients=email.dict().get("email"),
            body=html,
            subtype=MessageType.html)  # subtype=MessageType.plain
        fm = FastMail(conf)
        # fm.send_message(message, template_name='email.html')
        await fm.send_message(message)
        return JSONResponse(status_code=200, content={"message": "email has been sent"})
    

    How am I supposed to call it ? I tried this

    def main():
        email_simple_send()
        return None
    
    if __name__ == "__main__":
        main()
    

    But I get this error

    RuntimeWarning: coroutine 'email_simple_send' was never awaited  email_simple_send()
    

    Any idea ? Thanks.

    opened by marc-odp 6
  • fastapi_mail.errors.ConnectionErrors on gmail smtp

    fastapi_mail.errors.ConnectionErrors on gmail smtp

    I am getting the following error when trying the first basic example here:

    fastapi_mail.errors.ConnectionErrors: Exception raised (535, '5.7.8 Username and Password not accepted. Learn more at\n5.7.8 https://support.google.com/mail/?p=BadCredentials l33-20020a0568302b2100b005cdad9100desm5879477otv.40 - gsmtp'), check your credentials or email service configuration

    MAIL_USERNAME=asd
    MAIL_PASSWORD=<16-digit app password generated in gmail admin, 2step verification enabled>
    MAIL_FROM=<matching email>
    MAIL_PORT=587
    MAIL_SERVER=smtp.gmail.com
    MAILFROM_NAME=asd
    MAIL_TLS=1
    MAIL_SSL=0
    USE_CREDENTIALS=1
    VALIDATE_CERTS=1
    

    I tried with personal mail/pwd for testing and didn't work. Then I tried with validated mail/pwd currently being used in production on another (flask) app and it didn't work.

    opened by pepegc 6
  • intuitive email mocking with fastapi-mail

    intuitive email mocking with fastapi-mail

    A way to allow unit testing of application's email routes withpytestor unittest via mocking by fastapi_mail without actually sending out any emails.

    application.py

    conf = ConnectionConfig(
        MAIL_USERNAME = "YourUsername",
        MAIL_PASSWORD = "strong_password",
        MAIL_FROM = "[email protected]",
        MAIL_PORT = 587,
        MAIL_SERVER = "your mail server",
        MAIL_TLS = True,
        MAIL_SSL = False,
        TEMPLATE_FOLDER='./email templates folder',
        # if no indicated SUPPRESS_SEND defaults to 0 (false) as below
        SUPPRESS_SEND=0
    )
    
    fm = FastMail(conf)
    
    @app.post("/email")
    async def simple_send(email: EmailSchema) -> JSONResponse:
        message = MessageSchema(
            subject="Testing",
            recipients=email.dict().get("email"),  # List of recipients, as many as you can pass 
            body=html,
            subtype="html"
            )
        await fm.send_message(message)
        return JSONResponse(status_code=200, content={"message": "email has been sent"})
    

    test.py

    from application.py import fm
    
    # make this setting available as a fixture through conftest.py if you plan on using pytest
    fm.config.SUPPRESS_SEND = 1
    
    with fm.record_messages() as outbox:
        response = app.test_client.get("/email")
        assert len(outbox) == 1
        assert outbox[0].subject == "Testing"
    

    This will allow for more intuitive application mail testing via mocking and avoids bugging out email servers with dummy emails resulting in a potential block from that server, and this also eliminates the complexity of having to create a personal server to test sending outgoing mails.

    This PR was heavily influenced by the Flask-Mail testing function

    opened by maestro-1 6
  • How to send email as Jinja template with image?

    How to send email as Jinja template with image?

    I use FastAPI-Mail and Celery to send notifications in the background. I want to place the static image in the template and send it to the customer.

    I discovered that a url_for function returns an absolute URL and can be used in img tag as src.

    image

    The problem is that I get such an error, and I don't know how to solve it:

    Traceback (most recent call last):
      File "/usr/local/lib/python3.10/site-packages/celery/app/trace.py", line 451, in trace_task
        R = retval = fun(*args, **kwargs)
      File "/usr/local/lib/python3.10/site-packages/celery/app/trace.py", line 734, in __protected_call__
        return self.run(*args, **kwargs)
      File "/code/app/tasks/worker.py", line 17, in create_task
        send_birthday_reminder(
      File "/usr/local/lib/python3.10/site-packages/asgiref/sync.py", line 218, in __call__
        return call_result.result()
      File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 451, in result
        return self.__get_result()
      File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result
        raise self._exception
      File "/usr/local/lib/python3.10/site-packages/asgiref/sync.py", line 284, in main_wrap
        result = await self.awaitable(*args, **kwargs)
      File "/code/app/email/email.py", line 29, in send_birthday_reminder
        await fm.send_message(
      File "/usr/local/lib/python3.10/site-packages/fastapi_mail/fastmail.py", line 105, in send_message
        msg = await self.__prepare_message(message, template)
      File "/usr/local/lib/python3.10/site-packages/fastapi_mail/fastmail.py", line 71, in __prepare_message
        message.template_body = await self.__template_message_builder(
      File "/usr/local/lib/python3.10/site-packages/fastapi_mail/fastmail.py", line 85, in __template_message_builder
        return template.render(**template_data)
      File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 1301, in render
        self.environment.handle_exception()
      File "/usr/local/lib/python3.10/site-packages/jinja2/environment.py", line 936, in handle_exception
        raise rewrite_traceback_stack(source=source)
      File "/code/app/templates/email/birthday_reminder.html", line 1, in top-level template code
        {% extends './base.html' %}
      File "/code/app/templates/base.html", line 11, in top-level template code
        {% block content %} {% endblock %}
      File "/code/app/templates/email/birthday_reminder.html", line 4, in block 'content'
        <img src="{{ url_for('static', path='img/birthday_alarm.png') }}" />
      File "/usr/local/lib/python3.10/site-packages/jinja2/utils.py", line 83, in from_obj
        if hasattr(obj, "jinja_pass_arg"):
    jinja2.exceptions.UndefinedError: 'url_for' is undefined
    

    How can I solve this issue? Is there a better way to send a template with an image?

    opened by morento101 1
  • How to use a remote folder for TEMPLATE_FOLDER?

    How to use a remote folder for TEMPLATE_FOLDER?

    I want to use templates that are located on a different server, but I can not assign the path of remote folder to TEMPLATE_FOLDER. Here is the example path for a remote template that I wish to use:

    https://raw.githubusercontent.com/smohadjer/slaven/master/app/content/email_templates/camp.html

    Any idea how I can use this template for my email using TEMPLATE_FOLDER?

    opened by smohadjer 1
  • Can't upgrade to fastapi==0.88.0 because

    Can't upgrade to fastapi==0.88.0 because "fastapi-mail 1.2.2 depends on starlette<0.22.0"

    The same problem as in previous issue https://github.com/sabuhish/fastapi-mail/issues/157 but for the next version of the library. Do you consider to make less restrictive version dependency? 🙏🏻

    opened by ilBEastli 6
  • Allow setting of msgid and msgid domain

    Allow setting of msgid and msgid domain

    1. Extra 'msgid domain' ConnectionConfig parameter

    Set your own domain instead of the currently used local hostname.

    MAIL_MSGID_DOMAIN: Optional[str] = None

    1. Extra 'msgid domain' MailMsg parameter

    Dynamically set your own 'msgid domain' together with the MailMsg parameters.

    :param msgid_domain

    Overrides MAIL_MSGID_DOMAIN parameter

    1. Extra 'msgid' MailMsg parameter

    Dynamically set the 'msgid' together with the MailMsg parameters.

    :param msgid

    opened by mybooc 1
  • multipart html and plain text emails

    multipart html and plain text emails

    opened by msb 5
Releases(1.2.4)
Owner
Sabuhi
open science enthusiast loves python, go, and shell. Enjoys Linux environment.
Sabuhi
Churn Emails Inbox - Churn Emails Inbox Using Python

Churn Emails Inbox In this project, I have used the Python programming langauge

2 Nov 13, 2022
A small system for writing via email.

A small system for writing via email.

0 Nov 24, 2021
A python script that helps you understand why your E-Mail ended up in Spam

decode-spam-headers.py Whether you are trying to understand why a specific e-mail ended up in SPAM/Junk for your daily Administrative duties or for yo

Mariusz Banach 316 Jan 05, 2023
Collection of emails sent from the Hungarian gov and Viktor Orbán to the citizens of Hungary

Public list of Hungary and Viktor Orbán's emails since March 2021 Collection of emails sent from the Hungarian government and Viktor Orbán to the citi

Miguel Sozinho Ramalho 1 Mar 28, 2022
Automatically Send Custom Named Certificates via Mail

Welcome to Certificate Launchpad 🚀 Automatically Send Custom Named Certificates via Email Intro After any event, sending certificates to attendees or

Dc7 16 Oct 16, 2022
check disk storage's amount and if necessary, send alert message by email

DiskStorageAmountChecker What is this script? (このスクリプトは何ですか?) This script check disk storage's available amount of specified servers and send alerting

Hajime Kurita 1 Oct 22, 2021
Email-osint - Email OSINT tool written in python3

Email-osint - Email OSINT tool written in python3

Surtains 7 Nov 28, 2022
Use Django admin to manage drip campaign emails using querysets on Django's User model.

Django Drip Drip campaigns are pre-written sets of emails sent to customers or prospects over time. Django Drips lets you use the admin to manage drip

Zapier 630 Nov 16, 2022
A spammer to send mass emails to teachers. (Education Purposes only!)

Securly-Extension-Spammer A spammer to send mass emails to teachers. (Education Purposes only!) Setup Just go a securly blocked page(You can do this b

3 Jan 25, 2022
Command line interface for sending email using SMTP (ships with Gmail configuration).

mailsend Description Lightweight command line interface for sending email using SMTP. Default configuration is set for Gmail (smtp.gmail.com at port 5

Keith Mathe 1 Mar 22, 2022
A Discord Mod Mail bot made in python

Fish-Mail The mod mail bot for Fish Hosting Note: You are not allowed to remove the names in the credit command Note: If you want any ideas/commands a

28 Aug 30, 2022
A SMTP server for use as a pytest fixture that implements encryption and authentication.

SMTPDFix: Test email, locally A simple SMTP server based on aiosmtpd for use as a fixture with pytest that supports encryption and authentication. All

James Warne 11 Sep 03, 2022
A django package which act as a gateway to send and receive email with amazon SES.

django-email-gateway: Introduction: A Simple Django app to easily send emails, receive inbound emails from users with different email vendors like AWS

MicroPyramid 28 Nov 09, 2022
Python IMAP for Human beings

Imbox - Python IMAP for Humans Python library for reading IMAP mailboxes and converting email content to machine readable data Requirements Python (3.

Martin Rusev 1.1k Dec 30, 2022
Send e-mails asyncronously using cron

django-yubin Django Yubin allows the programmer to control when he wants to send the e-mail in this application, making the web application to answer

APSL 44 Sep 24, 2022
An API to send emails through python3's smtplib module.

An API to send emails through python3's smtplib module. Just configure your SMTP server credentials and you are ready to send a lot of emails through API, designed to be used as a newsletter service.

Adnan Ahmad 15 Nov 24, 2022
Esio_dev 3 Oct 15, 2021
You take an email and password from the combo list file and check it on mail.com

Brute-Force-mail tool information: Combo Type: email:pass Domains: All domains of the site Url: https://www.mail.com Api: ☑️ Proxy: No ☑️ The correct

6 Jun 05, 2022
Django module to easily send emails/sms/tts/push using django templates stored on database and managed through the Django Admin

Django-Db-Mailer Documentation available at Read the Docs. What's that Django module to easily send emails/push/sms/tts using django templates stored

LPgenerator 250 Dec 21, 2022
This is a bot that interacts with you over voice and sends mail.Uses speech_recognition,pyttsx3 and smtplib

AutoMail This is a bot that interacts with you over voice and sends mail Before you run the bot , go to mail.py and put your respective email address

Aditya Subrahmanya Bhat 2 Nov 04, 2022