package channel import ( "fmt" "github.com/gochat/gochat/internal/model" ) // ChannelEmail represents an Email (SMTP/IMAP) channel configuration. // Reference: Chatwoot app/models/channel/email.rb // // Chatwoot's ChannelEmail model attributes: // - email: The inbound email address (e.g. support@acme.com) // - forward_to_address: Email address for forwarding (alternative to IMAP) // - imap_enabled: Whether IMAP polling is enabled // - imap_address: IMAP server hostname // - imap_port: IMAP server port (typically 993 for SSL) // - imap_login: IMAP login/username // - imap_password: IMAP password // - imap_ssl: Whether to use SSL for IMAP connection // - smtp_enabled: Whether SMTP sending is enabled // - smtp_address: SMTP server hostname // - smtp_port: SMTP server port (typically 587 for TLS) // - smtp_login: SMTP login/username // - smtp_password: SMTP password // - smtp_ssl: Whether to use SSL/TLS for SMTP // // Chatwoot lifecycle hooks: // - before_validation :ensure_forward_to_address (sets default forwarding address) // - before_create :ensure_imap_connection (validates IMAP credentials) // - before_create :ensure_smtp_connection (validates SMTP credentials) // // gochat enhancements beyond Chatwoot: // - mailbox_name: Friendly name for the mailbox (for display) // - imap_ssl_mode: Explicit SSL mode (none/starttls/ssl) instead of boolean // - smtp_ssl_mode: Explicit SSL mode instead of boolean // - domain: Email domain for routing (e.g. "acme.com") // - use_reply_to: Whether to use Reply-To header for contact identification // ChannelEmail stores Email channel configuration for SMTP/IMAP. type ChannelEmail struct { model.Base // Account foreign key — links to the Account that owns this channel AccountID uint `gorm:"index;not null" json:"account_id"` // Inbox foreign key — links to the Inbox that wraps this channel InboxID uint `gorm:"not null;uniqueIndex" json:"inbox_id"` // Inbound email address — the address customers send emails to // Reference: Chatwoot EDITABLE_ATTRS = [:email] Email string `gorm:"size:255;not null" json:"email"` // Friendly name for the mailbox (e.g. "Acme Support") MailboxName string `gorm:"size:255" json:"mailbox_name,omitempty"` // Email domain for routing (extracted from Email, e.g. "acme.com") Domain string `gorm:"size:255;index" json:"domain"` // === IMAP Configuration === // Whether IMAP polling is enabled IMAPEnabled bool `gorm:"default:false" json:"imap_enabled"` // IMAP server hostname (e.g. "imap.gmail.com") IMAPAddress string `gorm:"size:255" json:"imap_address,omitempty"` // IMAP server port (typically 993 for SSL, 143 for plain) IMAPPort int `gorm:"default:993" json:"imap_port,omitempty"` // IMAP login/username IMAPLogin string `gorm:"size:255" json:"imap_login,omitempty"` // IMAP password (stored encrypted at application level) IMAPPassword string `gorm:"size:255" json:"imap_password,omitempty"` // IMAP SSL mode: "none", "starttls", "ssl" IMAPSSLMode string `gorm:"size:20;default:ssl" json:"imap_ssl_mode,omitempty"` // IMAP mailbox folder to monitor (e.g. "INBOX") IMAPFolder string `gorm:"size:255;default:INBOX" json:"imap_folder,omitempty"` // === SMTP Configuration === // Whether SMTP sending is enabled SMTPEnabled bool `gorm:"default:false" json:"smtp_enabled"` // SMTP server hostname (e.g. "smtp.gmail.com") SMTPAddress string `gorm:"size:255" json:"smtp_address,omitempty"` // SMTP server port (typically 587 for STARTTLS, 465 for SSL, 25 for plain) SMTPPort int `gorm:"default:587" json:"smtp_port,omitempty"` // SMTP login/username SMTPLogin string `gorm:"size:255" json:"smtp_login,omitempty"` // SMTP password (stored encrypted at application level) SMTPPassword string `gorm:"size:255" json:"smtp_password,omitempty"` // SMTP SSL mode: "none", "starttls", "ssl" SMTPSSLMode string `gorm:"size:20;default:starttls" json:"smtp_ssl_mode,omitempty"` // === Behavioral Configuration === // Whether to use Reply-To header for contact identification // When true, the Reply-To address is used instead of From address UseReplyTo bool `gorm:"default:false" json:"use_reply_to,omitempty"` // Whether to automatically group emails into conversations by thread AutoThread bool `gorm:"default:true" json:"auto_thread,omitempty"` // Maximum attachment size in bytes (0 = no limit) MaxAttachmentSize int64 `gorm:"default:0" json:"max_attachment_size,omitempty"` } func (ChannelEmail) TableName() string { return "channel_emails" } // GetChannelBase returns the ChannelBase for this channel. func (c *ChannelEmail) GetChannelBase() ChannelBase { return ChannelBase{ AccountID: c.AccountID, InboxID: c.InboxID, ChannelType: "email", } } // GetChannelType returns the channel type identifier. func (c *ChannelEmail) GetChannelType() string { return "email" } // IsIMAPConfigured returns true if IMAP connection parameters are set. func (c *ChannelEmail) IsIMAPConfigured() bool { return c.IMAPEnabled && c.IMAPAddress != "" && c.IMAPLogin != "" && c.IMAPPassword != "" } // IsSMTPConfigured returns true if SMTP connection parameters are set. func (c *ChannelEmail) IsSMTPConfigured() bool { return c.SMTPEnabled && c.SMTPAddress != "" && c.SMTPLogin != "" && c.SMTPPassword != "" } // IMAPConnectionString returns a human-readable IMAP connection summary. func (c *ChannelEmail) IMAPConnectionString() string { if !c.IsIMAPConfigured() { return "IMAP not configured" } return c.IMAPLogin + "@" + c.IMAPAddress + ":" + formatPort(c.IMAPPort) } // SMTPConnectionString returns a human-readable SMTP connection summary. func (c *ChannelEmail) SMTPConnectionString() string { if !c.IsSMTPConfigured() { return "SMTP not configured" } return c.SMTPLogin + "@" + c.SMTPAddress + ":" + formatPort(c.SMTPPort) } // formatPort converts port int to string, using defaults if zero. func formatPort(port int) string { if port == 0 { return "default" } return fmt.Sprintf("%d", port) }