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
Disposable email validator for python

disposable-email-validator installation pip install disposable-email-validator

1 Jan 05, 2022
Mail hosting made simple

Modoboa Modoboa is a mail hosting and management platform including a modern and simplified Web User Interface. It provides useful components such as

Modoboa 2.4k Jan 03, 2023
Simple, powerfull and nonobstructive django email middleware.

djmail djmail is a BSD Licensed, simple and nonobstructive django email middleware. Why use djmail? Because it: Sends emails asynchronously without ad

David BarragΓ‘n Merino 77 Aug 30, 2021
Bulk Email and certificate sending application

demir.ai E-mail services This application allows you to send automatic mass mail and automatic mass certificates to the people in your mailing list, m

Ahmet Furkan DEMIR 16 Nov 01, 2022
Send email in Python conveniently for gmail using yagmail

yagmail -- Yet Another GMAIL/SMTP client For the asynchronous asyncio version, look here: https://github.com/kootenpv/aioyagmail The goal here is to m

Pascal van Kooten 2.4k Dec 31, 2022
Send Multiple Mail From List With Python

Send Multiple Mail From List With Python You can send multiple e-mail using HTML themes with Python. Here is the e-mail information to be sent. #The m

MΓΌcahid Eker 1 Dec 23, 2021
An OSINT program that allows you to uncover a censored domain in an email adress

An OSINT program that allows you to uncover a censored domain in an email adress. Useful when you extract email from Instagram or Twitter password recovery function.

aet 3 Dec 16, 2021
xxnx its a simple smtp tool for mails spaming

xxnx its a simple smtp tool for mails spaming what is smpt? Simple Mail Transfer Protocol or smtp service. The Simple Mail Transfer Protocol (SMTP) is

0xD4$H 3 Feb 27, 2022
A simple free API that allows you to extract abuse emails from IPs.

Abuse-Email-API A simple free API that allows you to extract abuse emails from IPs. also isnt worth 500 dollars :) Requirements A Debian based OS The

Keratin 1 Dec 20, 2021
Euserv_extend captcha solver + pin code(Gmail)

Euserv_extend captcha solver + pin code(Gmail)

19 Nov 30, 2022
An email generator code in python language

An email generator code in python language. I have done it in the simplest way possible and with no link to an SMTP server. Generating infinite emails until CTRL+C . It is a code that can be used in

Kelvin Ndungu Wanja 1 Jan 17, 2022
Pysces (read: Pisces) is a program to help you send emails with an user-customizable time-based scheduling.

Pysces (Python Scheduled-Custom-Email-Sender) Pysces (read: Pisces) is a program to help you send emails with an user-customizable time-based email se

Peter 1 Jun 16, 2022
Email pass separator

email-pass-separator hii check out our new tool in kali linux use 'filename ' Dont forget to put inverted comma email:password separator Image Command

Hackers Tech 2 Sep 22, 2021
A simple email sender

Email-Sender Un semplice Email-Sender che utilizza il modulo smtplib con aggiunta di interfaccia grafica realizzata con il modulo tkinter Per il corre

Vincenzo Caliendo 0 Jan 14, 2022
Suplantar mails de empresas como google, facebook, github, etc...

Suplantar mails de empresas como google, facebook, github, etc...

piter 3 Feb 05, 2022
This simple python script uses cv2 to create and mail certificates to participants of workshops.

This simple python script uses cv2 to create and mail certificates to participants of workshops. Just collect the names and email ids of participants in a csv file (i used google docs), and place it

Sounder Rajendran 0 Dec 19, 2022
Temp-SMS-Receive - A Program Which Allows You To Receive Temp SMS

Welcome to Temp-SMS-Receive πŸ‘‹ A Program Which Allows You To Receive Temp SMS AP

Sandaru Ashen Fernando 21 Dec 10, 2022
A script based on an article I wrote on decluttering emails.

Decluttering_Email A script based on an article I wrote on decluttering emails. What does this program do? This program is a python script that sends

Ogheneyoma Obomate Okobiah 6 Oct 21, 2021
Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter.

Python Email Sender (PES) is a program made with Python using smtplib, socket and tkinter. This program was made for sender email to be a gmail account because that's what I used when testing it out,

Zacky2613 1 Aug 26, 2022