From ced694546302dbf5088bdad5a9510811e3c411ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Fi=C5=A1er?= Date: Sat, 1 Mar 2025 16:52:56 +0100 Subject: [PATCH 1/2] feat: Allow plaintext e-mails for SMTP Adds `--plaintext` flag which allows sending e-mails in plaintext with SMTP method. Also adds counterpart POP_PLAINTEXT. Not implemented for the Resend method. --- email.go | 6 +++--- main.go | 9 ++++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/email.go b/email.go index 1d9edd0..0ccddf7 100644 --- a/email.go +++ b/email.go @@ -42,7 +42,7 @@ func (m Model) sendEmailCmd() tea.Cmd { bcc := strings.Split(m.Bcc.Value(), ToSeparator) switch m.DeliveryMethod { case SMTP: - err = sendSMTPEmail(to, cc, bcc, m.From.Value(), m.Subject.Value(), m.Body.Value(), attachments) + err = sendSMTPEmail(to, cc, bcc, m.From.Value(), m.Subject.Value(), m.Body.Value(), plaintext, attachments) case Resend: err = sendResendEmail(to, cc, bcc, m.From.Value(), m.Subject.Value(), m.Body.Value(), attachments) default: @@ -65,7 +65,7 @@ const ( gmailSMTPPort = 587 ) -func sendSMTPEmail(to, cc, bcc []string, from, subject, body string, attachments []string) error { +func sendSMTPEmail(to, cc, bcc []string, from, subject, body string, plaintext bool, attachments []string) error { server := mail.NewSMTPClient() var err error @@ -116,7 +116,7 @@ func sendSMTPEmail(to, cc, bcc []string, from, subject, body string, attachments html := bytes.NewBufferString("") convertErr := goldmark.Convert([]byte(body), html) - if convertErr != nil { + if (plaintext) || (convertErr != nil) { email.SetBody(mail.TextPlain, body) } else { email.SetBody(mail.TextHTML, html.String()) diff --git a/main.go b/main.go index ffdda70..5671c10 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,10 @@ const envTrue = "true" // Resend delivery (as opposed to API key delivery). const PopOAuthResend = "POP_OAUTH_RESEND" +// PopPlaintext control whether the message should be sent in plaintext. +// Boolean, default `false` +const PopPlaintext = "POP_PLAINTEXT" + // ResendAPIKey is the environment variable that enables Resend as a delivery // method and uses it to send the email. const ResendAPIKey = "RESEND_API_KEY" //nolint:gosec @@ -71,6 +75,7 @@ var ( bcc []string subject string body string + plaintext bool attachments []string preview bool unsafe bool @@ -220,7 +225,7 @@ See "pop skill" for a full skill definition for AI agents.`, var err error switch deliveryMethod { case SMTP: - err = sendSMTPEmail(to, cc, bcc, from, subject, body, attachments) + err = sendSMTPEmail(to, cc, bcc, from, subject, body, plaintext, attachments) case Resend: err = sendResendEmail(to, cc, bcc, from, subject, body, attachments) default: @@ -373,6 +378,8 @@ func init() { rootCmd.Flags().StringSliceVarP(&attachments, "attach", "a", []string{}, "Email's attachments") rootCmd.Flags().StringSliceVarP(&to, "to", "t", []string{}, "Recipients") rootCmd.Flags().StringVarP(&body, "body", "b", "", "Email's contents") + envPlaintext := os.Getenv(PopPlaintext) == "true" + rootCmd.Flags().BoolVar(&plaintext, "plaintext", envPlaintext, "Whether to send email in plaintext") envFrom := os.Getenv(PopFrom) rootCmd.Flags().StringVarP(&from, "from", "f", envFrom, "Email's sender"+commentStyle.Render("($"+PopFrom+")")) rootCmd.Flags().StringVarP(&subject, "subject", "s", "", "Email's subject") From f639669ae0d861cec7c101367f80be71f4ef34de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Fi=C5=A1er?= Date: Wed, 16 Apr 2025 18:26:00 +0200 Subject: [PATCH 2/2] feat: Allow plaintext for resend --- email.go | 37 ++++++++++++++++++++----------------- main.go | 4 ++-- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/email.go b/email.go index 0ccddf7..c253cef 100644 --- a/email.go +++ b/email.go @@ -44,7 +44,7 @@ func (m Model) sendEmailCmd() tea.Cmd { case SMTP: err = sendSMTPEmail(to, cc, bcc, m.From.Value(), m.Subject.Value(), m.Body.Value(), plaintext, attachments) case Resend: - err = sendResendEmail(to, cc, bcc, m.From.Value(), m.Subject.Value(), m.Body.Value(), attachments) + err = sendResendEmail(to, cc, bcc, m.From.Value(), m.Subject.Value(), m.Body.Value(), plaintext, attachments) default: err = errors.New("[ERROR]: unknown delivery method") } @@ -135,25 +135,28 @@ func sendSMTPEmail(to, cc, bcc []string, from, subject, body string, plaintext b return nil } -func sendResendEmail(to, cc, bcc []string, from, subject, body string, attachments []string) error { +func sendResendEmail(to, cc, bcc []string, from, subject, body string, plaintext bool, attachments []string) error { client := resend.NewClient(resendAPIKey) html := bytes.NewBufferString("") - // If the conversion fails, we'll simply send the plain-text body. - if unsafe { - markdown := goldmark.New( - goldmark.WithRendererOptions( - renderer.WithUnsafe(), - ), - goldmark.WithExtensions( - extension.Strikethrough, - extension.Table, - extension.Linkify, - ), - ) - _ = markdown.Convert([]byte(body), html) - } else { - _ = goldmark.Convert([]byte(body), html) + // If the conversion fails or plaintext is requested, + // we'll simply send the plain-text body. + if !plaintext { + if unsafe { + markdown := goldmark.New( + goldmark.WithRendererOptions( + renderer.WithUnsafe(), + ), + goldmark.WithExtensions( + extension.Strikethrough, + extension.Table, + extension.Linkify, + ), + ) + _ = markdown.Convert([]byte(body), html) + } else { + _ = goldmark.Convert([]byte(body), html) + } } request := &resend.SendEmailRequest{ diff --git a/main.go b/main.go index 5671c10..a4a58ff 100644 --- a/main.go +++ b/main.go @@ -31,7 +31,7 @@ const envTrue = "true" const PopOAuthResend = "POP_OAUTH_RESEND" // PopPlaintext control whether the message should be sent in plaintext. -// Boolean, default `false` +// Boolean, default `false`. const PopPlaintext = "POP_PLAINTEXT" // ResendAPIKey is the environment variable that enables Resend as a delivery @@ -227,7 +227,7 @@ See "pop skill" for a full skill definition for AI agents.`, case SMTP: err = sendSMTPEmail(to, cc, bcc, from, subject, body, plaintext, attachments) case Resend: - err = sendResendEmail(to, cc, bcc, from, subject, body, attachments) + err = sendResendEmail(to, cc, bcc, from, subject, body, plaintext, attachments) default: err = fmt.Errorf("unknown delivery method") }