Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion patchwork/steps/ReadEmail/ReadEmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def run(self) -> dict:
)

for body in email_data.body:
rv["body"] += body.content
rv["body"] = body.content
break

return rv
1 change: 0 additions & 1 deletion patchwork/steps/ReadEmail/typed.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class ReadEmailInputs(__ReadEmailRequiredInputs, total=False):

class Attachment(TypedDict):
path: str
content: str


class ReadEmailOutputs(TypedDict):
Expand Down
50 changes: 36 additions & 14 deletions patchwork/steps/SendEmail/SendEmail.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
from __future__ import annotations

import smtplib
import textwrap
from datetime import datetime
from email.message import EmailMessage

from patchwork.common.utils.utils import mustache_render
from patchwork.step import Step
from patchwork.steps.ReadEmail.ReadEmail import ReadEmail
from patchwork.steps.SendEmail.typed import SendEmailInputs, SendEmailOutputs


class SendEmail(Step, input_class=SendEmailInputs, output_class=SendEmailOutputs):
def __init__(self, inputs):
super().__init__(inputs)
self.email_template_value = inputs.get("email_template_value", dict())
self.subject = inputs.get("subject", "Patchwork Execution Email")
self.body = inputs.get("body", "Patchwork Execution Email")
self.sender_email = inputs["sender_email"]
self.recipient_email = inputs["recipient_email"]
self.smtp_host = inputs.get("smtp_host", "smtp.gmail.com")
self.smtp_username = inputs["smtp_username"]
self.smtp_password = inputs["smtp_password"]
self.smtp_port = int(inputs.get("smtp_port", 25))
self.reply_message_id = inputs.get("reply_message_id")
self.is_ssl = bool(inputs.get("is_smtp_ssl", False))

self.sender_email = inputs["sender_email"]
self.recipient_email = inputs["recipient_email"]
email_template_value = inputs.get("email_template_value", dict())
self.subject = mustache_render(inputs.get("subject", "Patchwork Execution Email"), email_template_value)
self.body = mustache_render(inputs.get("body", "Patchwork Execution Email"), email_template_value)
self.reply_message_id = inputs.get("reply_message_id")
self.__handle_eml_file(inputs.get("reply_eml_file_path"))

def __handle_eml_file(self, eml_file: str):
if eml_file is None:
return

original_email_data = ReadEmail(dict(eml_file_path=eml_file)).run()
timestamp: datetime = original_email_data.get("datetime")
date_str = timestamp.date().strftime('%-d %b %Y')
time_str = timestamp.time().strftime('%H:%M')
from_ = original_email_data.get("from")
self.subject = original_email_data.get("subject")
self.body += f"\n\nOn {date_str} at {time_str}, {from_} wrote:\n\n" + textwrap.indent(original_email_data.get("body"), "> ")
self.reply_message_id = original_email_data.get("message_id")

def run(self) -> dict:
msg = EmailMessage()
msg.set_content(mustache_render(self.body, self.email_template_value))
msg["Subject"] = mustache_render(self.subject, self.email_template_value)
msg["From"] = self.sender_email
msg["To"] = self.recipient_email
if self.reply_message_id is not None:
msg.add_header("References", self.reply_message_id)
msg.add_header("In-Reply-To", self.reply_message_id)
msg = self.__create_email_message()

smtp_clazz = smtplib.SMTP
if self.is_ssl:
Expand All @@ -41,3 +52,14 @@ def run(self) -> dict:
mailserver.login(self.smtp_username, self.smtp_password)
mailserver.send_message(msg)
return dict()

def __create_email_message(self):
msg = EmailMessage()
msg.set_content(self.body)
msg["Subject"] = self.subject
msg["From"] = self.sender_email
msg["To"] = self.recipient_email
if self.reply_message_id is not None:
msg.add_header("References", self.reply_message_id)
msg.add_header("In-Reply-To", self.reply_message_id)
return msg
5 changes: 4 additions & 1 deletion patchwork/steps/SendEmail/typed.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from typing_extensions import Any, TypedDict
from typing_extensions import Any, TypedDict, Annotated

from patchwork.common.utils.step_typing import StepTypeConfig


class __SendEmailRequiredInputs(TypedDict):
Expand All @@ -16,6 +18,7 @@ class SendEmailInputs(__SendEmailRequiredInputs, total=False):
smtp_port: int
reply_message_id: str
is_smtp_ssl: str
reply_eml_file_path: Annotated[str, StepTypeConfig(is_path=True)]


class SendEmailOutputs(TypedDict):
Expand Down