Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

send_message as background task is not working #120

Closed
pepegc opened this issue Apr 30, 2022 · 21 comments
Closed

send_message as background task is not working #120

pepegc opened this issue Apr 30, 2022 · 21 comments

Comments

@pepegc
Copy link

pepegc commented Apr 30, 2022

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'},
)
@AlparslanKaraguney
Copy link

I have the same problem did anyone find a solution for this.

@ramiswailem
Copy link

how do you run the app? Uvicorn? Hypercorn? and which worker class are you use? can you switch between them?

@pepegc
Copy link
Author

pepegc commented May 12, 2022

hey @ramiswailem, I'm using uvicorn: uvicorn app.main:app --reload. Not sure what you mean by the worker class so I guess it's whatever the default is

@ramiswailem
Copy link

can you test it with:

gunicorn main:app -k uvicorn.workers.UvicornWorker

or with:

pip install hypercorn[uvloop]
hypercorn main:app --worker-class uvloop

@sabuhish
Copy link
Owner

sabuhish commented Jun 8, 2022

Hi, this issue is solved in the new version of fastapi-mail, please install 1.0.9 version.

@sabuhish sabuhish closed this as completed Jun 8, 2022
@pepegc
Copy link
Author

pepegc commented Jun 8, 2022

I was on 1.0.6.
I tried it now with 1.0.9 and it's still the same.
What about you @AlparslanKaraguney ?

@sabuhish sabuhish reopened this Jun 9, 2022
@sabuhish
Copy link
Owner

sabuhish commented Jun 9, 2022

Once I upgraded to 1.0.9 it was totally working, I was able to send with background task. Can you try, or could you tell me how you run it?

@app.get("/email")
async def send_in_background(
    background_tasks: BackgroundTasks,
   
    ) -> JSONResponse:

    message = MessageSchema(
        subject="Fastapi mail module",
        recipients=["mail_address"],
        body="Simple background task",
        )

    fm = FastMail(conf)

    background_tasks.add_task(fm.send_message,message)

    return JSONResponse(status_code=200, content={"message": "email has been sent"})

uvicorn app:app --port 8002 --reload

@pepegc
Copy link
Author

pepegc commented Jun 9, 2022

The code I have is exactly what I wrote above (1st comment).
Note the line that works (with await) and the one that does not (with add_task)

locally I run it with uvicorn app.main:app --reload
in production I have it on heroku with uvicorn app.main:app --host=0.0.0.0 --port=${PORT:-5000}

@vatsal-fpl
Copy link

Yes I have also the same issue since yesterday. I have tested the background task in main.py and it's not working but when I created a separate file for with similar endpoint with different name it's working. Somehow it's not working in my main.py

@vatsal-fpl
Copy link

Update
Guys check if you are using some kind of middleware. I was using the middleware to check request ip and when I removed it background tasks started running

@sabuhish
Copy link
Owner

sabuhish commented Jun 15, 2022

Well, I dont know what you guys have a configuration in the application, but I checked maybe 5 with an HTML template, and without it (simple approach), it works finely.

@vatsal-fpl
Copy link

vatsal-fpl commented Jun 15, 2022

I am taking name as input from users and putting it into my html template. I have also updated the latest version.

https://sabuhish.github.io/fastapi-mail/example/

@sabuhish
Copy link
Owner

it does not matter, still, I dont see any error, please check each version of the libraries you are using. Try to use the debugger.

@yubinees2
Copy link

yubinees2 commented Jun 16, 2022

I'm having the same issue on fastapi==0.78.0 and fastapi-mail==1.0.9.
I tried like below:

@app.post('/email')
async def send_signup_email(background_tasks: BackgroundTasks, email_form: EmailFormModel, email_user:EmailUserModel, debug:bool=False):
    message = MessageSchema(
        subject=email_form.subject,
        recipients=[email_user.to],
        template_body={'title': email_form.title,
             'name': email_user.name,
             'content': email_form.params.get("content", "test email."),
             'link': email_form.params.get("link", "https://www.test.com")
               },
        subtype='html',
    )

    if debug:
        print(message)
        await fm.send_message(message, template_name='template.html')
    else:
        background_tasks.add_task(fm.send_message, message, template_name='template.html')

    return 'Success'

Both debug=True/False option results same 'Success' but only await fm.send_message() sended email.
The interesting point is that the result with same backgroud_task.add_task works differently whether I called it through swaggerUI or curl -X POST, 0.0.0.0 or localhost, domain or internal ip. I guess it is likely to be related with uvicorn.

@keremnymn
Copy link

Exact same issue. await sends the mail but BackgroundTasks doesn't.

uvicorn==0.17.6
fastapi==0.78.0
fastapi-mail==1.0.9

@AsadBukharee
Copy link

some of the guy are using asyncio as mentioned here. Can you figure out the reason. I was going to use fastapi-mail in my project but now I am double mined.

@AsadBukharee
Copy link

AsadBukharee commented Jul 11, 2022

@sabuhish ,Is anybody working on this issue?

@AlparslanKaraguney
Copy link

I was on 1.0.6. I tried it now with 1.0.9 and it's still the same. What about you @AlparslanKaraguney ?

Sorry for late response. I did not test with 1.0.9 but i solved my problem by using celery worker. So in background task i use Celery to send the mail using fastapi mail.

@AsadBukharee
Copy link

AsadBukharee commented Jul 15, 2022

I am also using celery worker now , in windows we need to use eventlet or solo as follows.
pip install eventlet
celery -A worker worker --loglevel=INFO -P eventlet

it seems irrelevant but it may save time for others.

@jctissier
Copy link

Did anyone get this working with FastAPI for the background task only (no celery)? I have the most recent updated packages for uvicorn, fastapi & fastapi-mail. It used to work on previous versions but not anymore

@sabuhish
Copy link
Owner

Hi There! I have tried many times, and still I don't have any issues with the same config as you have mentioned, I have been able to send emails with background tasks. Here is the configuration I have made and directories where my files lives.

I have created app.py file and templates folder, inside templates folder I have signin.html

app.py

from pathlib import Path
from typing import List

from fastapi import BackgroundTasks, FastAPI
from fastapi_mail import ConnectionConfig, FastMail, MessageSchema
from pydantic import BaseModel, EmailStr
from starlette.responses import JSONResponse

conf = ConnectionConfig(
    MAIL_USERNAME = "my_username",
    MAIL_PASSWORD = "my_password",
    MAIL_FROM = "from_name",
    MAIL_PORT = 465,
    MAIL_SERVER = "mail_server",
    MAIL_FROM_NAME="Name",
    MAIL_SSL = True,
    TEMPLATE_FOLDER = Path(__file__).parent / 'templates',
)

   

app = FastAPI()

class EmailSchema(BaseModel):
    recipient: EmailStr
    a: str
    b: str

@app.post('/email')
async def send_signin_email(
        bg: BackgroundTasks,
        contents: EmailSchema,
    ) -> 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 ->this works
    bg.add_task(fm.send_message, message, template_name='signin.html') # DOES NOT WORK -> also works as expected

    return JSONResponse(
        status_code=200,
        content = {'message': 'email was sent'},
)

The background is just executed in either thread or just calls the async function:

https://github.com/encode/starlette/blob/master/starlette/background.py#L15

Apart from topics about background tasks that is not related to the fastapi-mail it is not part of the library, it is part of starlette, it is better to move the discussion there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants