Giter Site home page Giter Site logo

red-mail's Introduction

Hi, I'm Mikael

I am a finance graduate who really likes programming. Most of my projects are related data and finance and I program as a profession and as a hobby.

programming + finance + data

Mikael's Github stats

My favorite languages

Python Julia SQL

My hard skills

  • Data analysis (Seaborn, Matplotlib, Pandas)
  • Data engineering (T-SQL, PL/SQL, MongoDB)
  • Data science (Sklearn, Statsmodels, NLP)
  • Web development (Flask, FastAPI, CSS, HTML, Javascript)
  • Devops (unit testing, CI, Git, packaging)

My projects

Project Description Technologies
Rocketry A powerful scheduling framework Python
Red Mail Popular email sending library for Python Python
Red Box Email reader library for Python Python
Red Bird Repository patterns (database abstraction) Python
Synergy Automated system for news, stocks and business info Python, MongoDB, Ubuntu
ASM Trading simulator, thesis project Julia, Python, Latex

My background

Nationality Finnish
Education Master of Science (Finance)
Career Derivatives valuation in Corporate banking
Hobbies Climbing, programming (obviously)

Find me on

Github Linkedin Stack Overflow

red-mail's People

Contributors

drush0 avatar ejbills avatar floxicek avatar kimvanwyk avatar martino87r avatar miksus avatar rveachkc avatar s3nn3k3 avatar waghabond avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

red-mail's Issues

DOCS: disable jinja

I want to send a complex email: css and sh*t. I don't need jinja for this email, but I get errors when sending the email, since the css syntax tricks the jinja parser. Could fix it, double curly braces everywhere, but:
Is there a way to send the html without jinja parsing?
Regards

Traceback (most recent call last):
  File "./test_embed_redmail.py", line 136, in <module>
    email.send(
  File "/usr/local/lib/python3.8/dist-packages/redmail/email/sender.py", line 260, in send
    msg = self.get_message(
  File "/usr/local/lib/python3.8/dist-packages/redmail/email/sender.py", line 334, in get_message
    body.attach(
  File "/usr/local/lib/python3.8/dist-packages/redmail/email/body.py", line 113, in attach
    html, cids = self.render(
  File "/usr/local/lib/python3.8/dist-packages/redmail/email/body.py", line 173, in render
    html = super().render(html, tables=tables, jinja_params=jinja_params)
  File "/usr/local/lib/python3.8/dist-packages/redmail/email/body.py", line 76, in render
    return self.render_body(cont, jinja_params={**tables, **jinja_params})
  File "/usr/local/lib/python3.8/dist-packages/redmail/email/body.py", line 51, in render_body
    template = Environment().from_string(body)
  File "/home/user/.local/lib/python3.8/site-packages/jinja2/environment.py", line 1092, in from_string
    return cls.from_code(self, self.compile(source), gs, None)
  File "/home/user/.local/lib/python3.8/site-packages/jinja2/environment.py", line 757, in compile
    self.handle_exception(source=source_hint)
  File "/home/user/.local/lib/python3.8/site-packages/jinja2/environment.py", line 925, in handle_exception
    raise rewrite_traceback_stack(source=source)
  File "<unknown>", line 11, in template
jinja2.exceptions.TemplateSyntaxError: expected token 'end of print statement', got ':'

BUG: Fail on send with text body and attachments or only attachments (without body)

Describe the bug
Sending emails fails if the email has attachments and either no body at all (text or HTML) or has only text body. The reason is that the content type is not properly changed to multitype/mixed as email library does not change this with message.attach method.

To Reproduce

email = EmailSender(...)

email.send(
    receivers=["[email protected]"],
    subject="An attachment",
    text="A message",
    attachments={"a_file.html": Path("file.html")}
)

TypeError: Attach is not valid on a message with a non-multipart payload

Alternatively:

email.send(
    receivers=["[email protected]"],
    subject="An attachment",
    attachments={"a_file.html": Path("file.html")}
)

AttributeError: 'list' object has no attribute 'encode'

Expected behavior
Should not crash and should send the message.

ENH: Connection failures should not be misleading and say "please run connect() first"

Is your feature request related to a problem? Please describe.
When the connection fails, one receives the misleading exception: "please run connect() first" which is coming from red-mail calling smtplib.

Describe the solution you'd like
Provide an accurate and descriptive feedback that connection failed.

We ran the simplest red-mail script possible:

from redmail import EmailSender
from smtplib import SMTP

email = EmailSender(
    host="false-host",
    port=25
)

and got a totally misleading error message: "please run connect() first" instead of being told the connection failed.

Once we switched host to localhost the script ran fine.

ENH: Add support for relaying emails via `boto3` for use cases where apps running in AWS use IAM policies to authenticate against SES

Is your feature request related to a problem? Please describe.
Whilst Amazon SES offers relaying emails via SMTP there are cases where the environment is configured to use IAM policies for authentication. This applies to services like S3 for file storage or SES for email relay.

In these use cases the application would simply instantiate the boto3 client as:

import boto3
ses_client = boto3.client("ses", regional_name="ap-southeast-2")

and use their send_email function to send the message without the need of authenticating.

Describe the solution you'd like
If it's amicable with the design of this project then I would like to be able to initialise EmailSender with preconfigure boto3 client no different to how we can pass a custom SMTP instance.

import boto3
ses_client = boto3.client("ses", regional_name="ap-southeast-2")

sender = EmailSender(boto3_client=ses_client)

the send function would then use the boto3 client instead of an SMTP server to relay the emails.This way we get the array of functionality (namely templating) that this library offers and integrate into a platform like AWS.

Describe alternatives you've considered
At the moment our only alternative is to render Jinja templates on our own and then relay messages via boto3.

Additional context
This may be relevant to other cloud services like GCP or Azure. We've been working with the lovely folk @resendlabs who maintain a Python idiomatic SDK and could see this as an enhancement.

I would personally be willing to work on the boto3 and resend integration and provide a pull request :)

Iteration through images to be pasted on emails body. I have a dynamic contents of number of images. possible to iterate instead of hard code their names in dict?

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

BUG: Empty email being generated

Describe the bug
I'm having a problem with the MultiEmailHandler, that two emails are being sent. One valid email and one empty email. The empty email will still have the subject line, but the min_level_name and max_level_name will be set to "NOTSET".

I tried to manually flush or close the handler before the script ends, but that just makes it worse and causes even more empty emails.

To Reproduce
See below for testcase

One email will be valid, a second email will have a subject of "email test: NOTSET - NOTSET"

Expected behavior
A single email to be generated for the run of the script.

Email provider:

  • Email service: private
  • Application to view the email: not relevant

Environment (please complete the following information if relevant):

  • OS: Linux
  • Python version: 3.11
  • Red Mail version: 0.6.0

Additional context
Add any other context about the problem here.

#!/bin/python3
""" test MultiEmailHandler """
import logging.handlers
from redmail import MultiEmailHandler

# Create a custom logger
LOG = logging.getLogger(__name__)
LOG.setLevel(logging.INFO)

# Create email log handler
SMTP_SERVER = "email.server"
SENDER_EMAIL = "sender.email.address@server"
RECEIVER_EMAIL = ["receiver.email.address@server"]
SUBJECT="email test: {min_level_name} - {max_level_name}"

E_HANDLER = MultiEmailHandler(capacity=1024, **{
                                'host': SMTP_SERVER,
                                'port': 0,
                                'sender': SENDER_EMAIL,
                                'subject': SUBJECT,
                                'receivers': RECEIVER_EMAIL,
                                'text': """Logging level:
                                    {% for record in records %}
                                    Level name: {{ record.levelname }}
                                    Message: {{ record.msg }}
                                    {% endfor %}
                                """,
                                'html': """
                                    <ul>
                                    {% for record in records %}
                                        <li>Level name: {{ record.levelname }}</li>
                                        <li>Message: {{ record.msg }}</li>
                                    {% endfor %}
                                    </ul>
                                """}
                                )
E_HANDLER.setLevel(logging.INFO)
LOG.addHandler(E_HANDLER)

LOG.debug("Testing debug")
LOG.info("Testing info")
LOG.warning("Testing warning")
LOG.error("Testing error")

Send PDF on attachment

Hello,

I have a problem when I send a pdf, when I put it in the attachments the mail goes through without problem and is perfectly readable. However, when I receive it, I have an encoding error.

Thank you for your help.

ENH: Displaying status_code of the email status would be good for better error handling

I tried to find this feature but I didn't find it. so I am trying to get status_code of the email's status like "If the email was successfully sent or failed" and "If failed then How email failed", I mean what reason effected the email failure. If the console is showing error like -

smtplib.SMTPRecipientsRefused: {'user': (553, b'5.1.3 The recipient address is not a valid RFC-5321 address. Learn\n5.1.3 more at\n5.1.3 https://support.google.com/mail/answer/6596 ik12-20020a170902ab0cm2094481plb.177 - gsmtp')}

or

socket.gaierror: [Errno 11001] getaddrinfo failed

so, A developer will want to show or pass the appropriate message to the user in frontend on "What went wrong" or "What causes the email failure" ? but in this case It will only be seen as "something went wrong" (No status code or a clean message) to pass forward.

For Example -

email = EmailSender(
    host="smtp.gmail.com", port=587,
    username="xyz123", password="xyz123"
)

email.send(
    sender="[email protected],
   receivers=["[email protected]"],
   subject="An example email",
)

and If I try to print the EmailSender class calling variable print(email). Then it prints Class object Binary.

so It would be better to show more information about email just sent.

DOC: Outdated docstring

Is your feature request related to a problem? Please describe.
Docstrings are pretty outdated, for example EmailSender.send:

        Examples
        --------
            >>> sender = EmailSender(host="myserver", port=1234)
            >>> sender.send(
                sender="[email protected]",
                receiver="[email protected]",
                subject="Some news",
                html='<h1>Hi,</h1> Nice to meet you. Look at this: <img src="{{ my_image }}">',
                body_images={"my_image": Path("C:/path/to/img.png")}
            )
            >>> sender.send(
                sender="[email protected]",
                receiver="[email protected]",
                subject="Some news",
                html='<h1>Hi {{ name }},</h1> Nice to meet you. Look at this table: <img src="{{ my_table }}">',
                body_images={"my_image": Path("C:/path/to/img.png")},
                html_params={"name": "Jack"},
            )

The html_params was renamed to body_params even before the first release.

BUG: cannot send email using outlook

Hi everyone,

I'm having trouble automatically sending emails via my Outlook email address using Python. My organisation has MFA enabled, and I do not believe I can turn it off. The code I use is below:

outlook.username = username
outlook.password = password

print("sending email")
outlook.send(
    receivers=["[email protected]"], #NOTE: not email address I'm using, I'm using one that is legitimate
    subject="An example",
    text="Hi, this is an example."
)
print("email sent")

Expected behavior
I'm expecting to see the printed emails

sending email
email sent

Email provider:

  • Email service: Outlook
  • Application to view the email (unsure)

Environment (please complete the following information if relevant):

  • OS: MacOSX
  • Python version 3.11.5
  • Red Mail version 0.6.0

Issue on page /faq.html

I wanted to download all the attachments from a received mail. can provide the sample python code ?

BUG: Date header missing

Hello,

I stumbled upon an issue using my ISP's SMTP server (Orange, a french ISP). By default, they don't add the email's "Date" header if it's missing, and it's considered a required field by their servers.

Reproduction steps
Create an orange email address at :
https://login.orange.fr/signup/identity
Send an email using Redmail with the ISP's default SMTP server :
smtp.orange.fr (port 587)

Error
Every time, I get this kind of error email :

image

Additional info
Redmail version : 0.4.2
Python version : 3.8

I can PM the error email if needed.

I can send emails fine through their web client and using python's "email" package if I set the date using this :

[...]
from email.mime.multipart import MIMEMultipart
msg = MIMEMultipart('alternative')
msg['Date'] = utils.formatdate(localtime=True)

I believe the date field can be added in the "_create_body" function in "sender.py".
Maybe add a boolean parameter to allow adding the date, set to false by default, just in case it breaks something for someone else ?

I'm unsure if this should be a feature request or a bug, but since it's an error I can't get around using this library, I created a bug. If it needs to be a feature request, let me know.

Thanks for any help !

ENH: Have names to the inline images

Is your feature request related to a problem? Please describe.
The inline images are attached as "noname":
image
or more specifically, without a name. For library users that use it to send emails to clients, this may not be nice as that might sound unprofessional and suspicious.

Describe the solution you'd like
An option to give a name to the inline-image. Possibly have another name by default than "noname".

Describe alternatives you've considered
Serve the image from a server.

ENH: option that receivers do not see each other (but not BCC)

Is your feature request related to a problem? Please describe.

To use redmail for sending out a newsletter to all my users, I need them each to be the To: field but not to see each other's email addresses.

When using smtplib the recipients are not all added to a single email - they cannot see each others' names - whereas in redmail they are. That means I can't send an email to 1000 recipients without sharing all their emails (GDPR breach)

Describe the solution you'd like

I would like the option (and preferably the default) to be that recipients don't see each others emails

Describe alternatives you've considered

I could use BCC but that looks bad.

I could loop over them

for recip in recipients:
        email_sender.send(
            subject=subject,
            sender=sender,
            receivers=[recip],
            text=msg_text,
            html=msg_html
        )

but that seems like a lot of compiling the email for each of my recipients

I haven't looked to see how smtplib achieves this preferred outcome (maybe it does run a loop under the hood) but, for now I'll have to stick with that.

BUG: lazy logging incompatible with MultiEmailHandler?

Describe the bug
An issue I have with the MultiEmailHandler is that my log messages are written to be compliant with lazy logging (pylint warning W1201).

This works fine with the other loggers I use, but breaks with RedMail MultiEmailHandler, where my messages are full of '%s' where variables need to be.

e.g. this breaks RedMail and remains as "%s":

LOG.info("message %s", variable)

But this works:

LOG.info("message " + variable)

To Reproduce
Steps to reproduce the behavior:

  1. Use lazy logging function
  2. observe email, the %s will not be substituted for the variable

Expected behavior
%s to be substituted for the variable, like with other logging functions. Or at least some explanation in the docs about this.

Screenshots
If applicable, add screenshots to help explain your problem.

Email provider:

  • Email service: private
  • Application to view the email: not relevant

Environment (please complete the following information if relevant):

  • OS: Linux
  • Python version: 3.11
  • Red Mail version: 0.6.0

DOCS: Testing or how to get the email message

What should be improved:
How to test the messages could be better documented. Some might want to create tests for their application which also tests sending emails without actually sending them.

Improvement ideas:
The following could be presented:

  • How EmailSender.get_message works
  • How to mock the email server if one wants to test the EmailSender.send method

BUG: Scrambled email

Describe the bug
I have an AWS Lambda which sends email to users when needed. The email script is written in python. Mails are only sent when some events are produced. But some mails seems scrambled when user gets it in the inbox. See below screenshot. The html styles are not applied.Its a broken mail basically.

image

I use gmail to send it because the mail is bought from google mail with custom domain.

To Reproduce
This issue cannot be reproduced successfully. As i said, it only happens randomly.

Expected behavior
A clear and concise description of what you expected to happen.

Email provider:

  • Email service: Gmail
  • Application to view the email: Outlook web

Environment (please complete the following information if relevant):

  • AWS lambda
  • Python 3.9

Additional context

  • Redmail version: 0.6.0 (pip)

BUG: Emails with templates do not attach files correctly

First of all, thank you for this life-saving library: Easy templating has been a total game-changer.

Describe the bug
When using Jinja templates, attached files are not correctly attached to the email, as the message Content-Type is set to multipart/alternative instead of multipart/mixed.

Attachments are treated by mail clients as embedded content and thus not shown or recognized as attachments.

To Reproduce
Steps to reproduce the behavior:

1.- Create a simple snippet that includes both a template and an attachment (in any form):

redmail.send(
                subject='[%s] Email data for %s' % (str(instance),str(mail_id)),
                receivers=[str(email_address)],
                html_template='jinja_template.html',
                attachments=str(os.path.join(temp_path, str(attachment_filename))),
                body_params={'json_data': json_data,},
                body_images={
                    'logo': '/tmp/ogo.png',
                },
            )

Expected behavior
The mail is shown in the email client with the attachment.

Instead, the attachment is in the mail's source code but not available to download from the client.

Email provider:

  • Email service: private postfix
  • Application to view the email: Thunderbird, Gmail Client

Environment (please complete the following information if relevant):

  • OS: Linux
  • Python version: 3.8
  • Red Mail version: 0.3.1

Additional context

It is possible to fix this issue temporalily by modifying the 'attach' method from attachment.py to always set the message as mixed:

def attach(self, msg:EmailMessage):
        if msg.get_content_type() == "text/plain":
            # We need to change the content type
            # This occurs if no body is defined or only text is defined
            # The content type is therefore changed to multipart/mixed
            # See issue #23
            msg.make_mixed()
        else:
            try:
                msg.make_mixed()
            except Exception:
                pass
        for part in self._get_parts():
            msg.attach(part)

ENH: Is there a plan to add Plotly as image backend like matplotlib in the example?

Thanks for providing such useful module in python. It helps a lot in my work.
I used a lot with Plotly in my visualization analysis. I propose to use Plotly with redmail.

Demo code in my script:
"""
import plotly.graph_objects as go
def gen_plot():
fig = go.Figure()
image_io = BytesIO()
fig.write_image(image_io, format="png", engine='kaleido')
return image_io.getvalue()
"""
"""
body_images={"myplot': gen_plot()}
"""

ENH: Distribution lists

Is your feature request related to a problem? Please describe.
Often it is useful to have predefined email lists with various sets of people instead of typing the receivers always to the email.

Describe the solution you'd like
New attribute and arguments to EmailSender:

email = EmailSender(...)
email.distribution_lists = {
    'managers': ["[email protected]", "[email protected]"],
    'developers': ["[email protected]", "[email protected]"],
}
# Send to managers
email.send(
    distr="managers",
    subject="Something",
    ...
)

Also could support cc and bcc (distr_cc, distr_bcc). distribution_list could be a mapping so one can extend and have custom logic like:

class Distributions:

    def __getitem__(self, key):
        ... # Logic to find out the receivers
        return [...]

email = EmailSender(...)
email.distribution_lists = Distributions()

email.send(
    distr="managers",
    subject="Something",
    ...
)

Possibly there could even be a decorator to do such.

Describe alternatives you've considered
Create multiple EmailSender objects with different receivers.

ENH: add parameter to email.send() to allow rendered html to be modified before being emailed

Is your feature request related to a problem? Please describe.
I would like to modify the html after it is rendered by Jinja and before it is emailed. This is useful to minifty-html, cutting down payload size, and/or running premailer to help with converting css to inline styles on elements. This approach would also allow me to provide css as a jinja context variable, providing more flexibility in the final result.

Describe the solution you'd like
email.send() could accept an optional parameter 'finalized_html' that would be a callable. The callable would be used after jinja render(), but before the sender emails out the payload. Please see code below.

Describe alternatives you've considered
I've solved this by rendering the body html and then passing that to email.send(). Unfortunately, this means I need to create the jinja env, compile a Template and then let jinja render the html only to have red-mail repeat these steps. I'm still required to send the context (body_params) because the text template still needs it. Please see code below.

Additional context

from jinja2 import Environment, select_autoescape
from redmail import gmail
from minify_html import minify
from markupsafe import Markup
from premailer import Premailer

if __name__ == '__main__':
    premailer_ = Premailer(
        disable_validation=True,
        remove_classes=True,
    )
    transform = premailer_.transform

    jinja2env = Environment(
        autoescape=select_autoescape()
    )

    html = """
        <h1>Hi {{ name }}</h1>
    """

    body_params = {
        'name': 'Martin'
    }

    template_html = jinja2env.from_string(html)
    html_ = template_html.render(**body_params)

    gmail.username = '[email protected]'
    gmail.password = 'apppassword'
    email = gmail

    email.send(
        subject='email subject',
        receivers=['[email protected]'],
        html=minify(transform(html_)),
        text="""
            Hi {{ name }}
        """,
        body_params=body_params,
    )


if __name__ == 'WOULD_BE_NICE__main__':
    premailer_ = Premailer(
        disable_validation=True,
        remove_classes=True,
    )
    transform = premailer_.transform

    gmail.username = '[email protected]'
    gmail.password = 'apppassword'
    email = gmail
    
    html = """
        <h1>Hi {{ name }}</h1>
    """
    
    email.send(
        subject='email subject',
        receivers=['[email protected]'],
        finalize_html=lamdba html_: minify(transform(html_)),
        html="""
            <h1>Hi {{ name }}</h1>
        """,
        text="""
            Hi {{ name }}
        """,
        body_params={
            'name': 'Martin'
        }
    )

Base64 img

Hello, first of all thank you for this insane package.

I would like to add an image in base64 format in a <img src="{{ my_image_b64 }}" class="" /> using body_images = {}

Is this possible?

If yes can you show me an example, my image is a string in base64 format (data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAA .... )

Thanks a lot

issue with embed base64 image into jinja2 template

Hello Mikael,
Thank you for making red-mail, it's great helper.

Describe the bug
It seems it's not possible to embed base64 image into jinja2 template. Image is always attached to the email instead being embedded.

To Reproduce

Code:

    # picture is passed from python PIL from another function as arg
    # picture = base64.b64encode(buff.getvalue())
    # this way, I avoid saving and reading picture from disk, so base64 is super useful. 

    tp_decoded = base64.b64decode(picture)
    red_email.send(
        subject="The Subject",
        receivers=["[email protected]"],
        html_template="email/reset.html",
        body_images={
            "myimage": tp_decoded,
        },
    )

Template file:

<h1>Hello,</h1>
<p>
    {{ myimage }}
</p>

End result is attached image instead of embedded:

email

Expected behavior
Expecting that this would work the same way, as when no template is being used like in this example:

    tp_decoded = base64.b64decode(picture)
    red_email.send(
        subject="The Subject",
        receivers=["[email protected]"],
        html="""
            <h1>Hello,</h1>
            <p>Auth code is valid for 30 minutes</p>
            {{ myimage }}
            """,
        body_images={
            "myimage": tp_decoded,
        },
    )

Without template, image is embedded correctly:
email2

Email provider:

  • Email service: Gmail, Protonmail
  • Application to view the email: Web Gmail, Web Protonmail

Environment (please complete the following information if relevant):

  • OS: Linux
  • Python version [3.10.5]
  • Red Mail version [0.4.0]

ENH: Use defined Jinja envs with html and text

Describe the solution you'd like
Use the email.templates_html as the Jinja env if html is passed and similarly if text is passed. Currently, the envs are used only with template_(html/text) and with text/html a Jinja env is created on the fly.

Describe alternatives you've considered
To use the Jinja env, one could pass template_(html/text).

Additional context
This could have additional benefits with embedding Red Mail with Flask.

ENH: Add support for encrypting mail

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
I would like to be able to encrypt the contents of my mail, I would also like to be able to encrypt my password. Adding an API to redmail that would allow this to happen would be really good.

Describe the solution you'd like
A clear and concise description of what you want to happen.
Add API that offers a simple interface to encryption

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
python-gnupg with gpg-agent (on a headless box, so no gnome etc), keyring in desktop environment

Additional context
Add any other context or screenshots about the feature request here.
Whilst an encryption password might be necessary per email sent, it would be perfect if the encryption could be run non-interactively, obtaining the cleartext passphrase from a protected, audited file, or from the gpg keyring itself.

ENH: Remove Pandas as hard dependency

Describe the solution you'd like
Remove Pandas as hard dependency. Possibly handle them the same way as PIL and Matplotlib (see redmail/email/utils.py).

Different sending email address or alias when sending via gmail

Is your feature request related to a problem? Please describe.
No.

Describe the solution you'd like
Allow for different sending email address or alias when sending via gmail โ€“ i.e. from redmail import gmail.

Describe alternatives you've considered
None.

Additional context
n/a

Can't send email

just a simple dash app.


def send_email(to_email):
    
    outlook.username = '[email protected]'
    outlook.password = 'xxxxx'

    # And then you can send emails
    outlook.send(
        subject="Example email",
        receivers=[to_email],
        text="Hi, this is an email."
    )

getting this error:

smtplib.SMTPHeloError: (501, b'5.5.4 Invalid domain name [SCZP152CA0017.LAMP152.PROD.OUTLOOK.COM 2023-05-04T21:24:07.002Z 08DB4C5CCB756BD2]')

ENH: `async` support

Is your feature request related to a problem? Please describe.
I'm considering using red-mail to send emails in a backend application. Since connecting to the SMTP server is an I/O blocking operation, I would like to make use of async to avoid blocking other requests while the SMTP server or network are slow.

Describe the solution you'd like
I would like to be able to use red-mail in the following way.

from redmail import EmailSender
from fastapi import FastAPI

app = FastAPI()

@app.post("/send-email")
async def send_email() -> dict[str, str]:
    """Send an example email when this API endpoint is requested."""
    
    email = EmailSender(host='localhost', port=0)  # Real SMTP server would be on a remote network
    
    # By awaiting here, we allow other requests to be processed while waiting for I/O
    # Of course, using a different method name like `asend` would also be fine in order to keep the synchronous methods backwards compatible
    await email.send(  
        subject='async support in red-mail',
        sender="[email protected]",
        receivers=['[email protected]']
    )

    return {"status": "OK"}

Describe alternatives you've considered
Without async support I'd have to introduce additional complexity to get the same results.

  • manually creating threads or processes
  • fork red-mail and make it async
  • introduce a task queue and hand over email sending tasks

@Miksus If you're open to this, please let me know :) Thank you!

ENH: Provide various levels of logging in the code

Is your feature request related to a problem? Please describe.
When I encountered #63 I first sought to enable debug-level logging to see what the problem was. But upon inspecting the red-mail code, it became clear that there is no logging of any sort - info, debug, etc. This makes it harder to trace problems with code.

Describe the solution you'd like
Provide various levels of logging in the code.

ENH: Support non-TLS connections

Is your feature request related to a problem? Please describe.
The EmailSender could also support other than just TLS connection. Connecting to the SMTP server could be more customizable.

Describe the solution you'd like

Init could also take use_tls as an argument and the connection could be handled in a method to make subclassing convenient:

class EmailSender:
    ...
    def __init__(self, host:str, port:int, user_name:str=None, password:str=None, use_tls=True):
        self.host = host
        self.port = port
        self.use_tls = use_tls

...
    def send_message(self, msg):
        "Send the created message"
        server = self.connect()
        server.send_message(msg)
        
        server.quit() 

    def connect(self):
        "Connect to the SMTP server"
        user = self.user_name
        password = self.password
        
        server = self._cls_smtp_server(self.host, self.port)
        if self.use_tls:
            server.starttls()
        if user is not None or password is not None:
            server.login(user, password)
        return server

Also, the _cls_smtp_server could be public variable and meant to be changed.

Describe alternatives you've considered
There is no convenient alternative at the moment.

BUG: E-Mails aren't being sent, no error messages etc

email = EmailSender(
        host=config.smtp_server,
        port=config.smtp_port,
        user_name=config.smtp_user,
        password=config.smtp_pass
)
email.send(
    subject="My Subject",
    sender=config.smtp_user,
    receivers=["[email protected]"],
    text="Test"
)

Is not doing anything, emai is not receiving anything and there are also no messages. The only Error I get after like 3-5 minutes is the following:

raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

Can anyone validate that the latest version does indeed work with a simple example as above.

The same credentials work with the standard python smtp code with no issues eg.

server = smtplib.SMTP_SSL(config.smtp_server, config.smtp_port, context=ssl.create_default_context())
server.login(config.smtp_user, config.smtp_pass)
message = MIMEMultipart("alternative")
message["Subject"] = "Subject"
message["From"] = config.smtp_user
message["To"] = recipient

ENH: Logging Handlers

Is your feature request related to a problem? Please describe.
Even though the logging library has SMTPHandler, one might prefer to have more control and more customizable logging messages. For this purpose, it could be useful to implement such handlers from Red Mail also.

Describe the solution you'd like
Possibly two handlers: EmailHandler and MultiEmailHandler. The first one would send emails from each log record while the latter would send emails after n log records or after other condition is fulfilled.

Describe alternatives you've considered
One can also subclass the logging.Handler and logging.handlers.BufferingHandler by themselves and implement such their own.

Additional context
See:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.