Documentation
¶
Index ¶
- Constants
- type ABTestVariant
- type ABTestVariants
- type APIKey
- type Attachment
- type Bounce
- type BounceType
- type Campaign
- type CampaignMessage
- type CampaignMessageStatus
- type CampaignStatus
- type Contact
- type ContactList
- type ContactListMember
- type CustomFields
- type Domain
- type Email
- type EmailStatus
- type Event
- type EventCategory
- type FilterRule
- type FilterRules
- type InboundAttachmentMeta
- type InboundEmail
- type InboundEmailStatus
- type InboundSource
- type InvitationStatus
- type Language
- type OAuthAccount
- type OAuthProvider
- type OAuthProviderType
- type Plan
- type SMTPServer
- type Server
- type Session
- type Setting
- type StyleSheet
- type Subscriber
- type SubscriberList
- type SubscriberListMember
- type SubscriberListType
- type SubscriberListUnsubscribe
- type SubscriberStatus
- type Suppression
- type Template
- type TemplateData
- type TemplateLocalization
- type TemplateVersion
- type TrackedLink
- type TrackingEvent
- type TrackingEventType
- type User
- type UserEmailVerification
- type UserRole
- type UserSetting
- type Webhook
- type WebhookDelivery
- type WebhookDeliveryStatus
- type Workspace
- type WorkspaceInvitation
- type WorkspaceMember
- type WorkspaceRole
- type WorkspaceSSOConfig
Constants ¶
const ( // ServerSecurityModePermissive allows any user whose sender domain matches // allowed_domains to use this server, regardless of domain ownership. ServerSecurityModePermissive = "permissive" // ServerSecurityModeStrict requires the user to have verified ownership of // the sender domain (via TXT record) before the server is available to them. ServerSecurityModeStrict = "strict" )
const ( EncryptionNone = "none" // Plain text (port 25) EncryptionSTARTTLS = "starttls" // Upgrade via STARTTLS (port 587) EncryptionSSL = "ssl" // Implicit TLS (port 465) )
Encryption modes for SMTP connections.
const ( SMTPStatusEnabled = "enabled" // Valid and available for sending SMTPStatusDisabled = "disabled" // Manually disabled by user SMTPStatusInvalid = "invalid" // Validation failed (bad credentials, connection error) )
SMTP server status values.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ABTestVariant ¶
type ABTestVariant struct {
Name string `json:"name"`
Subject string `json:"subject"`
TemplateID *uint `json:"template_id,omitempty"`
SplitPercentage int `json:"split_percentage"`
}
ABTestVariant represents a single variant in an A/B test campaign.
type ABTestVariants ¶
type ABTestVariants []ABTestVariant
ABTestVariants is a JSON array of A/B test variants stored as TEXT.
func (*ABTestVariants) Scan ¶
func (v *ABTestVariants) Scan(value interface{}) error
type APIKey ¶
type APIKey struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Name string `json:"name" gorm:"not null"`
KeyHash string `json:"-" gorm:"not null"`
KeyPrefix string `json:"key_prefix" gorm:"not null"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt *time.Time `json:"expires_at"`
LastUsedAt *time.Time `json:"last_used_at"`
Revoked bool `json:"revoked" gorm:"default:false"`
AllowedIPs pq.StringArray `json:"allowed_ips" gorm:"type:text[]"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type Attachment ¶
type Attachment struct {
Filename string `json:"filename"`
Content string `json:"content,omitempty"`
ContentType string `json:"content_type"`
// StorageKey is set when the attachment content is stored in blob storage
// (S3 or filesystem). When present, Content may be empty and the actual
// bytes should be fetched from the blob store using this key.
StorageKey string `json:"storage_key,omitempty"`
}
Attachment represents a file attachment in an email.
type Bounce ¶
type Bounce struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
EmailID uint `json:"email_id" gorm:"index;not null"`
Recipient string `json:"recipient" gorm:"not null"`
Type BounceType `json:"type" gorm:"not null"`
Reason string `json:"reason"`
CreatedAt time.Time `json:"created_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
Email Email `json:"-" gorm:"foreignKey:EmailID"`
}
type BounceType ¶
type BounceType string
const ( BounceTypeHard BounceType = "hard" BounceTypeSoft BounceType = "soft" BounceTypeComplaint BounceType = "complaint" )
type Campaign ¶
type Campaign struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Name string `json:"name" gorm:"not null"`
Subject string `json:"subject" gorm:"not null"`
FromEmail string `json:"from_email" gorm:"not null"`
FromName string `json:"from_name"`
TemplateID uint `json:"template_id" gorm:"index;not null"`
TemplateVersionID *uint `json:"template_version_id,omitempty" gorm:"index"`
Language string `json:"language" gorm:"default:'en'"`
TemplateData TemplateData `json:"template_data,omitempty" gorm:"type:text"`
Status CampaignStatus `json:"status" gorm:"type:varchar(20);default:'draft';not null;index"`
ListID uint `json:"list_id" gorm:"index;not null"`
SendRate int `json:"send_rate" gorm:"default:0"`
SendAtLocalTime bool `json:"send_at_local_time" gorm:"default:false"`
ABTestEnabled bool `json:"ab_test_enabled" gorm:"default:false"`
ABTestVariants ABTestVariants `json:"ab_test_variants,omitempty" gorm:"type:text"`
ABTestWinner string `json:"ab_test_winner,omitempty"`
ScheduledAt *time.Time `json:"scheduled_at,omitempty"`
StartedAt *time.Time `json:"started_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
// Snapshot captures the aggregated stats at soft-delete time so analytics
// for past sends survive after CampaignMessage rows are purged.
Snapshot TemplateData `json:"snapshot,omitempty" gorm:"type:text"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type CampaignMessage ¶
type CampaignMessage struct {
ID uint `json:"id" gorm:"primaryKey"`
CampaignID uint `json:"campaign_id" gorm:"uniqueIndex:idx_campaign_sub;not null;index"`
SubscriberID uint `json:"subscriber_id" gorm:"uniqueIndex:idx_campaign_sub;not null;index"`
EmailID *uint `json:"email_id,omitempty" gorm:"index"`
Status CampaignMessageStatus `json:"status" gorm:"type:varchar(20);default:'pending';not null;index"`
ErrorMessage string `json:"error_message,omitempty"`
Variant string `json:"variant,omitempty" gorm:"size:50"`
SentAt *time.Time `json:"sent_at,omitempty"`
OpenedAt *time.Time `json:"opened_at,omitempty"`
ClickedAt *time.Time `json:"clicked_at,omitempty"`
BouncedAt *time.Time `json:"bounced_at,omitempty"`
UnsubscribedAt *time.Time `json:"unsubscribed_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
Campaign Campaign `json:"-" gorm:"foreignKey:CampaignID"`
Subscriber Subscriber `json:"-" gorm:"foreignKey:SubscriberID"`
}
type CampaignMessageStatus ¶
type CampaignMessageStatus string
const ( CampaignMsgPending CampaignMessageStatus = "pending" CampaignMsgQueued CampaignMessageStatus = "queued" CampaignMsgSent CampaignMessageStatus = "sent" CampaignMsgFailed CampaignMessageStatus = "failed" CampaignMsgSkipped CampaignMessageStatus = "skipped" )
type CampaignStatus ¶
type CampaignStatus string
const ( CampaignStatusDraft CampaignStatus = "draft" CampaignStatusScheduled CampaignStatus = "scheduled" CampaignStatusSending CampaignStatus = "sending" CampaignStatusSent CampaignStatus = "sent" CampaignStatusPaused CampaignStatus = "paused" CampaignStatusCancelled CampaignStatus = "cancelled" )
type Contact ¶
type Contact struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Email string `json:"email" gorm:"not null"`
Name string `json:"name" gorm:"default:''"`
SentCount int64 `json:"sent_count" gorm:"default:0;not null"`
FailCount int64 `json:"fail_count" gorm:"default:0;not null"`
LastSentAt *time.Time `json:"last_sent_at"`
CreatedAt time.Time `json:"created_at"`
}
type ContactList ¶
type ContactList struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Name string `json:"name" gorm:"not null"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
Members []ContactListMember `json:"-" gorm:"foreignKey:ListID"`
}
type ContactListMember ¶
type ContactListMember struct {
ID uint `json:"id" gorm:"primaryKey"`
ListID uint `json:"list_id" gorm:"uniqueIndex:idx_list_email;not null"`
Email string `json:"email" gorm:"uniqueIndex:idx_list_email;not null"`
Name string `json:"name"`
Data string `json:"data" gorm:"type:text"` // JSON metadata
CreatedAt time.Time `json:"created_at"`
List ContactList `json:"-" gorm:"foreignKey:ListID"`
}
type CustomFields ¶
type CustomFields map[string]interface{}
CustomFields is a JSON map stored as TEXT in the database.
func (*CustomFields) Scan ¶
func (cf *CustomFields) Scan(value interface{}) error
type Domain ¶
type Domain struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Domain string `json:"domain" gorm:"not null"`
OwnershipVerified bool `json:"ownership_verified" gorm:"default:false"`
SPFVerified bool `json:"spf_verified" gorm:"default:false"`
DKIMVerified bool `json:"dkim_verified" gorm:"default:false"`
DMARCVerified bool `json:"dmarc_verified" gorm:"default:false"`
VerificationToken string `json:"verification_token" gorm:"not null"`
CreatedAt time.Time `json:"created_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
func (*Domain) IsFullyVerified ¶
IsFullyVerified returns true when ownership is confirmed and all DNS checks pass.
func (*Domain) IsOwnershipVerified ¶
IsOwnershipVerified returns true when domain ownership has been confirmed via TXT record.
type Email ¶
type Email struct {
ID uint `json:"id" gorm:"primaryKey"`
UUID string `json:"uuid" gorm:"type:uuid;default:gen_random_uuid();uniqueIndex;not null"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
APIKeyID *uint `json:"api_key_id" gorm:"index"`
Sender string `json:"sender" gorm:"not null"`
Recipients pq.StringArray `json:"recipients" gorm:"type:text[];not null"`
Subject string `json:"subject" gorm:"not null"`
TemplateName string `json:"template_name,omitempty"`
HTMLBody string `json:"html_body"`
TextBody string `json:"text_body"`
AttachmentsJSON string `json:"attachments_json,omitempty" gorm:"type:text"`
HeadersJSON string `json:"headers_json,omitempty" gorm:"type:text"`
ListUnsubscribeURL string `json:"list_unsubscribe_url,omitempty" gorm:"type:text"`
ListUnsubscribePost bool `json:"list_unsubscribe_post,omitempty"`
Status EmailStatus `json:"status" gorm:"default:pending;not null"`
ErrorMessage string `json:"error_message"`
RetryCount int `json:"retry_count" gorm:"default:0;not null"`
CreatedAt time.Time `json:"created_at"`
SentAt *time.Time `json:"sent_at"`
ScheduledAt *time.Time `json:"scheduled_at"`
Provider string `json:"provider,omitempty" gorm:"index;size:32"`
SMTPHostname string `json:"smtp_hostname,omitempty"`
User User `json:"-" gorm:"foreignKey:UserID"`
APIKey APIKey `json:"-" gorm:"foreignKey:APIKeyID"`
}
type EmailStatus ¶
type EmailStatus string
const ( EmailStatusPending EmailStatus = "pending" EmailStatusQueued EmailStatus = "queued" EmailStatusProcessing EmailStatus = "processing" EmailStatusSent EmailStatus = "sent" EmailStatusFailed EmailStatus = "failed" EmailStatusSuppressed EmailStatus = "suppressed" EmailStatusScheduled EmailStatus = "scheduled" )
type Event ¶
type Event struct {
ID uint `json:"id" gorm:"primaryKey"`
Category EventCategory `json:"category" gorm:"index;not null"`
Type string `json:"type" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
ActorID *uint `json:"actor_id" gorm:"index"`
ActorName string `json:"actor_name"`
ClientIP string `json:"client_ip,omitempty" gorm:"size:45"`
Message string `json:"message" gorm:"not null"`
Metadata string `json:"metadata" gorm:"type:text"`
CreatedAt time.Time `json:"created_at" gorm:"index"`
}
type EventCategory ¶
type EventCategory string
const ( EventCategoryUser EventCategory = "user" EventCategoryEmail EventCategory = "email" EventCategorySystem EventCategory = "system" EventCategoryAudit EventCategory = "audit" )
type FilterRule ¶
type FilterRules ¶
type FilterRules []FilterRule
func (*FilterRules) Scan ¶
func (fr *FilterRules) Scan(value interface{}) error
type InboundAttachmentMeta ¶ added in v0.6.0
type InboundAttachmentMeta struct {
Filename string `json:"filename"`
ContentType string `json:"content_type"`
Size int64 `json:"size"`
StorageKey string `json:"storage_key,omitempty"`
// Content is only populated when no blob store is configured (dev fallback).
Content string `json:"content,omitempty"`
}
InboundAttachmentMeta describes one inbound attachment stored in blob storage. Serialized into InboundEmail.AttachmentsJSON.
type InboundEmail ¶ added in v0.6.0
type InboundEmail struct {
ID uint `json:"id" gorm:"primaryKey"`
UUID string `json:"uuid" gorm:"type:uuid;default:gen_random_uuid();uniqueIndex;not null"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
DomainID uint `json:"domain_id" gorm:"index;not null"`
MessageID string `json:"message_id" gorm:"index"`
Sender string `json:"sender" gorm:"not null"`
Recipients pq.StringArray `json:"recipients" gorm:"type:text[];not null"`
Subject string `json:"subject"`
TextBody string `json:"text_body" gorm:"type:text"`
HTMLBody string `json:"html_body" gorm:"type:text"`
AttachmentsJSON string `json:"attachments_json,omitempty" gorm:"type:text"`
HeadersJSON string `json:"headers_json,omitempty" gorm:"type:text"`
RawStorageKey string `json:"raw_storage_key,omitempty"`
DedupHash string `json:"-" gorm:"index"`
Size int64 `json:"size"`
SpamScore *float64 `json:"spam_score,omitempty"`
Status InboundEmailStatus `json:"status" gorm:"default:received;not null"`
Source InboundSource `json:"source" gorm:"not null"`
ErrorMessage string `json:"error_message,omitempty"`
RetryCount int `json:"retry_count" gorm:"default:0;not null"`
ReceivedAt time.Time `json:"received_at" gorm:"not null"`
ForwardedAt *time.Time `json:"forwarded_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
Domain Domain `json:"-" gorm:"foreignKey:DomainID"`
}
type InboundEmailStatus ¶ added in v0.6.0
type InboundEmailStatus string
const ( InboundStatusReceived InboundEmailStatus = "received" InboundStatusForwarded InboundEmailStatus = "forwarded" InboundStatusFailed InboundEmailStatus = "failed" InboundStatusRejected InboundEmailStatus = "rejected" )
type InboundSource ¶ added in v0.6.0
type InboundSource string
const ( InboundSourceSMTP InboundSource = "smtp" InboundSourceWebhook InboundSource = "webhook" )
type InvitationStatus ¶
type InvitationStatus string
const ( InvitationStatusPending InvitationStatus = "pending" InvitationStatusAccepted InvitationStatus = "accepted" InvitationStatusDeclined InvitationStatus = "declined" )
type Language ¶
type Language struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Code string `json:"code" gorm:"not null;size:10"`
Name string `json:"name" gorm:"not null"`
IsDefault bool `json:"is_default" gorm:"default:false"`
CreatedAt time.Time `json:"created_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type OAuthAccount ¶
type OAuthAccount struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"uniqueIndex:idx_user_provider;not null"`
ProviderID uint `json:"provider_id" gorm:"uniqueIndex:idx_user_provider;not null"`
ProviderUserID string `json:"provider_user_id" gorm:"uniqueIndex:idx_provider_ext_id;not null"`
Email string `json:"email"`
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
AccessToken string `json:"-" gorm:"type:text"`
RefreshToken string `json:"-" gorm:"type:text"`
TokenExpiresAt *time.Time `json:"-"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
Provider OAuthProvider `json:"-" gorm:"foreignKey:ProviderID"`
}
OAuthAccount links an external OAuth identity to a local user.
type OAuthProvider ¶
type OAuthProvider struct {
ID uint `json:"id" gorm:"primaryKey"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Name string `json:"name" gorm:"not null"`
Slug string `json:"slug" gorm:"uniqueIndex;not null"`
Type OAuthProviderType `json:"type" gorm:"not null"`
ClientID string `json:"-" gorm:"not null"`
ClientSecret string `json:"-" gorm:"not null"`
Issuer string `json:"issuer"`
AuthURL string `json:"auth_url"`
TokenURL string `json:"token_url"`
UserInfoURL string `json:"userinfo_url"`
Scopes string `json:"scopes" gorm:"default:'openid email profile'"`
Enabled bool `json:"enabled" gorm:"default:true;not null"`
Hidden bool `json:"hidden" gorm:"default:false;not null"`
AutoRegister bool `json:"auto_register" gorm:"default:true"`
AllowedDomains string `json:"allowed_domains"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
OAuthProvider stores configuration for an OAuth/OIDC identity provider.
type OAuthProviderType ¶
type OAuthProviderType string
const ( OAuthProviderGoogle OAuthProviderType = "google" OAuthProviderOIDC OAuthProviderType = "oidc" )
type Plan ¶
type Plan struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"uniqueIndex;not null"`
Description string `json:"description"`
IsDefault bool `json:"is_default" gorm:"default:false"`
IsActive bool `json:"is_active" gorm:"default:true"`
DailyRateLimit int `json:"daily_rate_limit" gorm:"default:0"`
HourlyRateLimit int `json:"hourly_rate_limit" gorm:"default:0"`
MaxAttachmentSizeMB int `json:"max_attachment_size_mb" gorm:"default:0"`
MaxBatchSize int `json:"max_batch_size" gorm:"default:0"`
MaxAPIKeys int `json:"max_api_keys" gorm:"default:0"`
MaxDomains int `json:"max_domains" gorm:"default:0"`
MaxSMTPServers int `json:"max_smtp_servers" gorm:"default:0"`
MaxWorkspaces int `json:"max_workspaces" gorm:"default:0"`
EmailLogRetentionDays int `json:"email_log_retention_days" gorm:"default:0"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Plan defines a usage package that can be assigned to workspaces. Each plan specifies rate limits, resource quotas, and retention policies. A value of 0 for any limit field means unlimited.
type SMTPServer ¶
type SMTPServer struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Host string `json:"host" gorm:"not null"`
Port int `json:"port" gorm:"not null"`
Username string `json:"username"`
Password string `json:"-"`
Encryption string `json:"encryption" gorm:"default:none;not null"`
MaxRetries int `json:"max_retries" gorm:"default:0;not null"`
AllowedEmails pq.StringArray `json:"allowed_emails" gorm:"type:text[]"`
Status string `json:"status" gorm:"default:enabled;not null"`
ValidationError string `json:"validation_error" gorm:"type:text"`
ValidatedAt *time.Time `json:"validated_at"`
CreatedAt time.Time `json:"created_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
func (*SMTPServer) AfterFind ¶
func (s *SMTPServer) AfterFind(tx *gorm.DB) error
AfterFind decrypts the password after reading from the database.
func (*SMTPServer) BeforeSave ¶
func (s *SMTPServer) BeforeSave(tx *gorm.DB) error
BeforeSave encrypts the password before writing to the database. Uses AES-256-GCM if POSTA_ENCRYPTION_KEY is set, otherwise base64.
func (*SMTPServer) IsEnabled ¶
func (s *SMTPServer) IsEnabled() bool
IsEnabled returns true when the server can be used for delivery.
type Server ¶
type Server struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"not null"`
Host string `json:"host" gorm:"not null"`
Port int `json:"port" gorm:"not null"`
Username string `json:"username"`
Password string `json:"-"`
Encryption string `json:"encryption" gorm:"default:none;not null"`
MaxRetries int `json:"max_retries" gorm:"default:0;not null"`
Status string `json:"status" gorm:"default:enabled;not null"`
AllowedDomains pq.StringArray `json:"allowed_domains" gorm:"type:text[]"`
SecurityMode string `json:"security_mode" gorm:"default:permissive;not null"`
SentCount int64 `json:"sent_count" gorm:"default:0;not null"`
FailedCount int64 `json:"failed_count" gorm:"default:0;not null"`
ValidationError string `json:"validation_error" gorm:"type:text"`
ValidatedAt *time.Time `json:"validated_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Server represents a shared SMTP server managed by platform administrators. Unlike per-user SMTPServer records, a Server is available across multiple user accounts based on the sender domain.
func (*Server) BeforeSave ¶
BeforeSave encrypts the password before writing to the database. Uses AES-256-GCM if POSTA_ENCRYPTION_KEY is set, otherwise base64.
func (*Server) ToSMTPServer ¶
func (s *Server) ToSMTPServer() *SMTPServer
ToSMTPServer converts this shared Server into the SMTPServer format used by the SMTP sender, so existing send logic can be reused without modification.
type Session ¶
type Session struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
JTI string `json:"jti" gorm:"uniqueIndex;not null;size:36"` // JWT ID (UUID)
IPAddress string `json:"ip_address"`
UserAgent string `json:"user_agent"`
Revoked bool `json:"revoked" gorm:"default:false;not null"`
CreatedAt time.Time `json:"created_at"`
ExpiresAt time.Time `json:"expires_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
Session tracks an active JWT session for a user.
type Setting ¶
type Setting struct {
ID uint `json:"id" gorm:"primaryKey"`
Key string `json:"key" gorm:"uniqueIndex;not null"`
Value string `json:"value" gorm:"type:text"`
Type string `json:"type" gorm:"default:string;not null"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Setting represents a platform-wide configuration entry managed by admins. Settings are stored as key-value pairs with a type hint for the frontend.
type StyleSheet ¶
type StyleSheet struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Name string `json:"name" gorm:"not null"`
CSS string `json:"css"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type Subscriber ¶
type Subscriber struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"uniqueIndex:idx_sub_scope_email;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"uniqueIndex:idx_sub_scope_email;index"`
Email string `json:"email" gorm:"uniqueIndex:idx_sub_scope_email;not null"`
Name string `json:"name" gorm:"default:''"`
Status SubscriberStatus `json:"status" gorm:"type:varchar(20);default:'subscribed';not null;index"`
CustomFields CustomFields `json:"custom_fields" gorm:"type:text"`
Timezone string `json:"timezone" gorm:"size:50;default:''"`
Language string `json:"language" gorm:"size:10;default:''"`
SubscribedAt *time.Time `json:"subscribed_at"`
UnsubscribedAt *time.Time `json:"unsubscribed_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type SubscriberList ¶
type SubscriberList struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Name string `json:"name" gorm:"not null"`
Description string `json:"description"`
Type SubscriberListType `json:"type" gorm:"type:varchar(10);default:'static';not null"`
FilterRules FilterRules `json:"filter_rules,omitempty" gorm:"type:text"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type SubscriberListMember ¶
type SubscriberListMember struct {
ID uint `json:"id" gorm:"primaryKey"`
ListID uint `json:"list_id" gorm:"uniqueIndex:idx_sublist_sub;not null"`
SubscriberID uint `json:"subscriber_id" gorm:"uniqueIndex:idx_sublist_sub;not null;index"`
CreatedAt time.Time `json:"created_at"`
List SubscriberList `json:"-" gorm:"foreignKey:ListID"`
Subscriber Subscriber `json:"-" gorm:"foreignKey:SubscriberID"`
}
type SubscriberListType ¶
type SubscriberListType string
const ( SubscriberListTypeStatic SubscriberListType = "static" SubscriberListTypeDynamic SubscriberListType = "dynamic" )
type SubscriberListUnsubscribe ¶ added in v0.6.0
type SubscriberListUnsubscribe struct {
ID uint `json:"id" gorm:"primaryKey"`
ListID uint `json:"list_id" gorm:"uniqueIndex:idx_listunsub_sub;not null"`
SubscriberID uint `json:"subscriber_id" gorm:"uniqueIndex:idx_listunsub_sub;not null;index"`
Reason string `json:"reason" gorm:"size:64"`
UnsubscribedAt time.Time `json:"unsubscribed_at"`
List SubscriberList `json:"-" gorm:"foreignKey:ListID"`
Subscriber Subscriber `json:"-" gorm:"foreignKey:SubscriberID"`
}
SubscriberListUnsubscribe records that a specific subscriber has opted out
type SubscriberStatus ¶
type SubscriberStatus string
const ( SubscriberStatusSubscribed SubscriberStatus = "subscribed" SubscriberStatusUnsubscribed SubscriberStatus = "unsubscribed" SubscriberStatusBounced SubscriberStatus = "bounced" SubscriberStatusComplained SubscriberStatus = "complained" )
type Suppression ¶
type Suppression struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Email string `json:"email" gorm:"not null"`
Reason string `json:"reason"`
CreatedAt time.Time `json:"created_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type Template ¶
type Template struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Name string `json:"name" gorm:"not null"`
DefaultLanguage string `json:"default_language" gorm:"default:en;not null"`
ActiveVersionID *uint `json:"active_version_id,omitempty" gorm:"uniqueIndex"`
Description string `json:"description"`
SampleData string `json:"sample_data"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
User User `json:"-" gorm:"foreignKey:UserID"`
ActiveVersion *TemplateVersion `json:"active_version,omitempty" gorm:"foreignKey:ActiveVersionID;constraint:false"`
}
type TemplateData ¶
type TemplateData map[string]interface{}
TemplateData is a JSON map for template variable substitution.
func (*TemplateData) Scan ¶
func (td *TemplateData) Scan(value interface{}) error
type TemplateLocalization ¶
type TemplateLocalization struct {
ID uint `json:"id" gorm:"primaryKey"`
VersionID uint `json:"version_id" gorm:"uniqueIndex:idx_version_language;not null"`
Language string `json:"language" gorm:"uniqueIndex:idx_version_language;not null;size:10"`
SubjectTemplate string `json:"subject_template" gorm:"not null"`
HTMLTemplate string `json:"html_template"`
TextTemplate string `json:"text_template"`
BuilderJSON string `json:"builder_json,omitempty" gorm:"type:text"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
Version TemplateVersion `json:"-" gorm:"foreignKey:VersionID;constraint:OnDelete:CASCADE"`
}
type TemplateVersion ¶
type TemplateVersion struct {
ID uint `json:"id" gorm:"primaryKey"`
TemplateID uint `json:"template_id" gorm:"index;not null"`
Version int `json:"version" gorm:"not null"`
StyleSheetID *uint `json:"stylesheet_id,omitempty" gorm:"index"`
SampleData string `json:"sample_data"`
CreatedAt time.Time `json:"created_at"`
StyleSheet *StyleSheet `json:"stylesheet,omitempty" gorm:"foreignKey:StyleSheetID;constraint:OnDelete:SET NULL"`
Localizations []TemplateLocalization `json:"localizations,omitempty" gorm:"foreignKey:VersionID"`
}
type TrackedLink ¶
type TrackedLink struct {
ID uint `json:"id" gorm:"primaryKey"`
CampaignID uint `json:"campaign_id" gorm:"index;not null"`
OriginalURL string `json:"original_url" gorm:"type:text;not null"`
Hash string `json:"hash" gorm:"uniqueIndex;not null"`
ClickCount int64 `json:"click_count" gorm:"default:0;not null"`
CreatedAt time.Time `json:"created_at"`
Campaign Campaign `json:"-" gorm:"foreignKey:CampaignID"`
}
TrackedLink stores rewritten links for click tracking.
type TrackingEvent ¶
type TrackingEvent struct {
ID uint `json:"id" gorm:"primaryKey"`
CampaignMessageID uint `json:"campaign_message_id" gorm:"index;not null"`
EventType TrackingEventType `json:"event_type" gorm:"type:varchar(20);not null;index"`
TrackedLinkID *uint `json:"tracked_link_id,omitempty" gorm:"index"`
IP string `json:"ip" gorm:"size:45"`
UserAgent string `json:"user_agent" gorm:"type:text"`
CreatedAt time.Time `json:"created_at" gorm:"index"`
CampaignMessage CampaignMessage `json:"-" gorm:"foreignKey:CampaignMessageID"`
TrackedLink *TrackedLink `json:"-" gorm:"foreignKey:TrackedLinkID"`
}
TrackingEvent records individual open/click/unsubscribe events.
type TrackingEventType ¶
type TrackingEventType string
const ( TrackingEventOpen TrackingEventType = "open" TrackingEventClick TrackingEventType = "click" TrackingEventUnsubscribe TrackingEventType = "unsubscribe" )
type User ¶
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"not null;default:''"`
Email string `json:"email" gorm:"uniqueIndex;not null"`
PasswordHash string `json:"-" gorm:"not null"`
Role UserRole `json:"role" gorm:"default:user;not null"`
TwoFactorSecret string `json:"-" gorm:"type:text"`
TwoFactorEnabled bool `json:"two_factor_enabled" gorm:"default:false"`
Active bool `json:"active" gorm:"default:true;not null"`
RequireVerifiedDomain bool `json:"require_verified_domain" gorm:"default:false"`
AuthMethod string `json:"auth_method" gorm:"default:'password';not null"`
AvatarURL string `json:"avatar_url"`
PlanID *uint `json:"plan_id" gorm:"index"`
ScheduledDeletionAt *time.Time `json:"scheduled_deletion_at"`
EmailVerifiedAt *time.Time `json:"email_verified_at"`
CreatedAt time.Time `json:"created_at"`
LastLoginAt *time.Time `json:"last_login_at"`
Plan Plan `json:"-" gorm:"foreignKey:PlanID"`
}
type UserEmailVerification ¶ added in v0.6.0
type UserSetting ¶
type UserSetting struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"uniqueIndex;not null"`
Timezone string `json:"timezone" gorm:"default:UTC"`
DefaultSenderName string `json:"default_sender_name"`
DefaultSenderEmail string `json:"default_sender_email"`
EmailNotifications bool `json:"email_notifications" gorm:"default:true"`
NotificationEmail string `json:"notification_email"`
WebhookRetryCount int `json:"webhook_retry_count" gorm:"default:3"`
DefaultTemplateID *uint `json:"default_template_id"`
APIKeyExpiryDays int `json:"api_key_expiry_days" gorm:"default:90"`
BounceAutoSuppress bool `json:"bounce_auto_suppress" gorm:"default:true"`
DefaultLanguage string `json:"default_language" gorm:"size:10;default:'en'"`
DailyReport bool `json:"daily_report" gorm:"default:false"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
UserSetting stores per-user preferences. Each user has at most one row.
type Webhook ¶
type Webhook struct {
ID uint `json:"id" gorm:"primaryKey"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
URL string `json:"url" gorm:"not null"`
Events pq.StringArray `json:"events" gorm:"type:text[];not null"`
Filters pq.StringArray `json:"filters" gorm:"type:text[]"`
Secret string `json:"secret,omitempty" gorm:"type:varchar(64);not null;default:''"`
CreatedAt time.Time `json:"created_at"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type WebhookDelivery ¶
type WebhookDelivery struct {
ID uint `json:"id" gorm:"primaryKey"`
WebhookID uint `json:"webhook_id" gorm:"index;not null"`
UserID uint `json:"user_id" gorm:"index;not null"`
WorkspaceID *uint `json:"workspace_id,omitempty" gorm:"index"`
Event string `json:"event" gorm:"not null"`
Status WebhookDeliveryStatus `json:"status" gorm:"type:varchar(16);not null;index"`
HTTPStatusCode int `json:"http_status_code"`
ErrorMessage string `json:"error_message,omitempty"`
Attempt int `json:"attempt" gorm:"not null;default:1"`
CreatedAt time.Time `json:"created_at"`
Webhook Webhook `json:"-" gorm:"foreignKey:WebhookID"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
WebhookDelivery records the result of delivering a webhook notification.
type WebhookDeliveryStatus ¶
type WebhookDeliveryStatus string
WebhookDeliveryStatus represents the outcome of a webhook delivery attempt.
const ( WebhookDeliverySuccess WebhookDeliveryStatus = "success" WebhookDeliveryFailed WebhookDeliveryStatus = "failed" )
type Workspace ¶
type Workspace struct {
ID uint `json:"id" gorm:"primaryKey"`
Name string `json:"name" gorm:"not null"`
Slug string `json:"slug" gorm:"uniqueIndex;not null"`
Description string `json:"description"`
OwnerID uint `json:"owner_id" gorm:"index;not null"`
PlanID *uint `json:"plan_id" gorm:"index"`
DefaultLanguage string `json:"default_language" gorm:"size:10;default:'en'"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Owner User `json:"-" gorm:"foreignKey:OwnerID"`
Plan Plan `json:"-" gorm:"foreignKey:PlanID"`
Members []WorkspaceMember `json:"-" gorm:"foreignKey:WorkspaceID"`
}
type WorkspaceInvitation ¶
type WorkspaceInvitation struct {
ID uint `json:"id" gorm:"primaryKey"`
WorkspaceID uint `json:"workspace_id" gorm:"index;not null"`
Email string `json:"email" gorm:"not null"`
Role WorkspaceRole `json:"role" gorm:"not null;default:viewer"`
Token string `json:"-" gorm:"uniqueIndex;not null"`
Status InvitationStatus `json:"status" gorm:"not null;default:pending"`
InvitedBy uint `json:"invited_by" gorm:"not null"`
ExpiresAt time.Time `json:"expires_at" gorm:"not null"`
CreatedAt time.Time `json:"created_at"`
Workspace Workspace `json:"-" gorm:"foreignKey:WorkspaceID"`
Inviter User `json:"-" gorm:"foreignKey:InvitedBy"`
}
type WorkspaceMember ¶
type WorkspaceMember struct {
ID uint `json:"id" gorm:"primaryKey"`
WorkspaceID uint `json:"workspace_id" gorm:"uniqueIndex:idx_workspace_user;not null"`
UserID uint `json:"user_id" gorm:"uniqueIndex:idx_workspace_user;not null"`
Role WorkspaceRole `json:"role" gorm:"not null;default:viewer"`
CreatedAt time.Time `json:"created_at"`
Workspace Workspace `json:"-" gorm:"foreignKey:WorkspaceID"`
User User `json:"-" gorm:"foreignKey:UserID"`
}
type WorkspaceRole ¶
type WorkspaceRole string
const ( WorkspaceRoleOwner WorkspaceRole = "owner" WorkspaceRoleAdmin WorkspaceRole = "admin" WorkspaceRoleEditor WorkspaceRole = "editor" WorkspaceRoleViewer WorkspaceRole = "viewer" )
func (WorkspaceRole) CanEdit ¶
func (r WorkspaceRole) CanEdit() bool
CanEdit returns true if the role can create/modify resources.
func (WorkspaceRole) CanManageMembers ¶
func (r WorkspaceRole) CanManageMembers() bool
CanManageMembers returns true if the role can invite/remove members.
func (WorkspaceRole) CanView ¶
func (r WorkspaceRole) CanView() bool
CanView returns true if the role has any access.
func (WorkspaceRole) IsOwner ¶
func (r WorkspaceRole) IsOwner() bool
IsOwner returns true if the role is owner.
type WorkspaceSSOConfig ¶
type WorkspaceSSOConfig struct {
ID uint `json:"id" gorm:"primaryKey"`
WorkspaceID uint `json:"workspace_id" gorm:"uniqueIndex;not null"`
ProviderID uint `json:"provider_id" gorm:"not null"`
EnforceSSO bool `json:"enforce_sso" gorm:"default:false"`
AutoProvision bool `json:"auto_provision" gorm:"default:true"`
AllowedDomains string `json:"allowed_domains"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Workspace Workspace `json:"-" gorm:"foreignKey:WorkspaceID"`
Provider OAuthProvider `json:"-" gorm:"foreignKey:ProviderID"`
}
WorkspaceSSOConfig controls SSO enforcement for a workspace.
Source Files
¶
- abtest.go
- api_key.go
- bounce.go
- campaign.go
- campaign_message.go
- contact.go
- contact_list.go
- domain.go
- email.go
- event.go
- inbound_email.go
- language.go
- oauth_account.go
- oauth_provider.go
- plan.go
- server.go
- session.go
- setting.go
- smtp_server.go
- stylesheet.go
- subscriber.go
- subscriber_list.go
- suppression.go
- template.go
- template_localization.go
- template_version.go
- tracking.go
- user.go
- user_email_verification.go
- user_setting.go
- webhook.go
- webhook_delivery.go
- workspace.go
- workspace_sso.go