mirror of
https://github.com/abhinavxd/libredesk.git
synced 2025-10-23 05:11:57 +00:00
130 lines
3.4 KiB
Go
130 lines
3.4 KiB
Go
// Package email provides functionality for an email inbox with multiple SMTP servers and IMAP clients.
|
|
package email
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/abhinavxd/libredesk/internal/inbox"
|
|
"github.com/knadh/smtppool"
|
|
"github.com/zerodha/logf"
|
|
)
|
|
|
|
const (
|
|
ChannelEmail = "email"
|
|
)
|
|
|
|
// Config holds the email inbox configuration with multiple SMTP servers and IMAP clients.
|
|
type Config struct {
|
|
SMTP []SMTPConfig `json:"smtp"`
|
|
IMAP []IMAPConfig `json:"imap"`
|
|
From string `json:"from"`
|
|
}
|
|
|
|
// SMTPConfig represents an SMTP server's credentials with the smtppool options.
|
|
type SMTPConfig struct {
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
AuthProtocol string `json:"auth_protocol"`
|
|
TLSType string `json:"tls_type"`
|
|
TLSSkipVerify bool `json:"tls_skip_verify"`
|
|
EmailHeaders map[string]string `json:"email_headers"`
|
|
smtppool.Opt `json:",squash"` // SMTP pool options.
|
|
}
|
|
|
|
// IMAPConfig holds IMAP client credentials and configuration.
|
|
type IMAPConfig struct {
|
|
Host string `json:"host"`
|
|
Port int `json:"port"`
|
|
Username string `json:"username"`
|
|
Password string `json:"password"`
|
|
Mailbox string `json:"mailbox"`
|
|
ReadInterval string `json:"read_interval"`
|
|
ScanInboxSince string `json:"scan_inbox_since"`
|
|
TLSType string `json:"tls_type"`
|
|
TLSSkipVerify bool `json:"tls_skip_verify"`
|
|
}
|
|
|
|
// Email represents the email inbox with multiple SMTP servers and IMAP clients.
|
|
type Email struct {
|
|
id int
|
|
smtpPools []*smtppool.Pool
|
|
imapCfg []IMAPConfig
|
|
headers map[string]string
|
|
lo *logf.Logger
|
|
from string
|
|
messageStore inbox.MessageStore
|
|
userStore inbox.UserStore
|
|
wg sync.WaitGroup
|
|
}
|
|
|
|
// Opts holds the options required for the email inbox.
|
|
type Opts struct {
|
|
ID int
|
|
Headers map[string]string
|
|
Config Config
|
|
Lo *logf.Logger
|
|
}
|
|
|
|
// New returns a new instance of the email inbox.
|
|
func New(store inbox.MessageStore, userStore inbox.UserStore, opts Opts) (*Email, error) {
|
|
pools, err := NewSmtpPool(opts.Config.SMTP)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
e := &Email{
|
|
id: opts.ID,
|
|
headers: opts.Headers,
|
|
from: opts.Config.From,
|
|
imapCfg: opts.Config.IMAP,
|
|
lo: opts.Lo,
|
|
smtpPools: pools,
|
|
messageStore: store,
|
|
userStore: userStore,
|
|
}
|
|
return e, nil
|
|
}
|
|
|
|
// Identifier returns the unique identifier of the inbox which is the database ID.
|
|
func (e *Email) Identifier() int {
|
|
return e.id
|
|
}
|
|
|
|
// Receive starts reading incoming messages for each IMAP client.
|
|
func (e *Email) Receive(ctx context.Context) error {
|
|
for _, cfg := range e.imapCfg {
|
|
e.wg.Add(1)
|
|
go func(cfg IMAPConfig) {
|
|
defer e.wg.Done()
|
|
if err := e.ReadIncomingMessages(ctx, cfg); err != nil {
|
|
e.lo.Error("error reading incoming messages", "error", err)
|
|
}
|
|
}(cfg)
|
|
}
|
|
e.wg.Wait()
|
|
return nil
|
|
}
|
|
|
|
// Close cloes email channel by closing the smtp pool
|
|
func (e *Email) Close() error {
|
|
return e.closeSMTPPool()
|
|
}
|
|
|
|
// FromAddress returns the from address for this inbox.
|
|
func (e *Email) FromAddress() string {
|
|
return e.from
|
|
}
|
|
|
|
// Channel returns the channel name for this inbox.
|
|
func (e *Email) Channel() string {
|
|
return ChannelEmail
|
|
}
|
|
|
|
// closeSMTPPool closes the smtp pool.
|
|
func (e *Email) closeSMTPPool() error {
|
|
for _, p := range e.smtpPools {
|
|
p.Close()
|
|
}
|
|
return nil
|
|
}
|