mirror of
https://github.com/makeplane/plane.git
synced 2026-07-13 14:01:45 +02:00
* feat: migrated email service to plane-ee * feat: added build files * fix: goreleaser for naming the binary * fix: github CI * feat: added certification generation * fix: github CI * feat: changed name for email service * minor fixes to docker file and cert gen process. Added k8s manifest for testing * removed build-email action * added eks-cloudflare-setup instructions * added support to gke * modfied container ports from 25 465 587 to 10025 10465 10587 * cleanup yml files * email docs cleanup * added email service build action in plane cloud github action file * fix: typo fix of email service image name * fix: replaced base action for email service * fix: registry name * fix: uses in email service * feat:modified-k8s-proxy * updated k8s manifest * updated k8s template * fix: email build action * fix image name * fixed the spam detection mechanism * upated k8s manifest --------- Co-authored-by: Manish Gupta <manish@plane.so> Co-authored-by: akshat5302 <akshatjain9782@gmail.com> Co-authored-by: sriram veeraghanta <veeraghanta.sriram@gmail.com> Co-authored-by: Manish Gupta <59428681+mguptahub@users.noreply.github.com>
109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
package services
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"io"
|
|
"log"
|
|
"plane/email/pkg/utils/parser"
|
|
"strings"
|
|
|
|
"github.com/emersion/go-message/mail"
|
|
"github.com/emersion/go-smtp"
|
|
)
|
|
|
|
type Session struct {
|
|
From string
|
|
To []string
|
|
}
|
|
|
|
func (s *Session) AuthPlain(username, password string) error {
|
|
// log.Println("Authenticating user", username)
|
|
if AuthenticateUser(username, password) {
|
|
return nil
|
|
}
|
|
return errors.New("invalid username or password")
|
|
}
|
|
|
|
func (s *Session) Mail(from string, opts *smtp.MailOptions) error {
|
|
s.From = from
|
|
// log.Printf("Mail from: %s", from)
|
|
return nil
|
|
}
|
|
|
|
func (s *Session) Rcpt(to string, opts *smtp.RcptOptions) error {
|
|
// log.Printf("Rcpt to: %s", to)
|
|
s.To = append(s.To, to)
|
|
return nil
|
|
}
|
|
|
|
func (s *Session) Data(r io.Reader) error {
|
|
// log.Println("Receiving message")
|
|
if s.From == "" || len(s.To) == 0 {
|
|
return errors.New("missing from or to address")
|
|
}
|
|
// Read email data
|
|
var buf bytes.Buffer
|
|
if _, err := io.Copy(&buf, r); err != nil {
|
|
return err
|
|
}
|
|
data := buf.Bytes()
|
|
|
|
// Basic spam check
|
|
if parser.IsBacklistedDomain(string(s.From)) {
|
|
log.Printf("Detected spam domain from %s", s.From)
|
|
return errors.New("message rejected")
|
|
}
|
|
if parser.IsSpam(string(data)) {
|
|
log.Printf("Detected spam from %s", s.From)
|
|
return errors.New("message rejected")
|
|
}
|
|
|
|
// Parse the email
|
|
mr, err := mail.CreateReader(bytes.NewReader(data))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
header := mr.Header
|
|
subject, _ := header.Subject()
|
|
// log.Printf("Subject: %v", subject)
|
|
|
|
var body string
|
|
for {
|
|
p, err := mr.NextPart()
|
|
if err == io.EOF {
|
|
break
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch h := p.Header.(type) {
|
|
case *mail.InlineHeader:
|
|
// This is the message's text (can be plain-text or HTML)
|
|
b, _ := io.ReadAll(p.Body)
|
|
body += string(b)
|
|
case *mail.AttachmentHeader:
|
|
// This is an attachment
|
|
filename, _ := h.Filename()
|
|
log.Printf("Got attachment: %v", filename)
|
|
}
|
|
}
|
|
|
|
// Store the email
|
|
if err := SaveEmail(s.From, strings.Join(s.To, ", "), subject, body); err != nil {
|
|
return err
|
|
}
|
|
log.Printf("Email processed successfully: %s", s.From)
|
|
return nil
|
|
}
|
|
|
|
func (s *Session) Reset() {
|
|
s.From = ""
|
|
s.To = nil
|
|
}
|
|
|
|
func (s *Session) Logout() error {
|
|
return nil
|
|
}
|