Documentation ¶
Index ¶
- Constants
- Variables
- func AllowAuthorize(service api.Service, mb *api.Mailbox, useSsl api.Maybe) bool
- func CheckErrorsCount(client *Client, maxErrorsPerConnection int)
- func DefaultNewFileFromDelivery(proxy MessageReceiverProxy, delivery Delivery, hostName string, ...) (filename string, dataSize int64, err error)
- func DeliveryAddHeaderAs(d *Delivery, name, value string, first bool)
- func DeliveryDelHeader(d *Delivery, name string)
- func DeliverySetHeader(d *Delivery, name string, value string, first bool)
- func DovecotMessageFilenameV2(delivery *Delivery, proxy MessageReceiverProxy, hostname string, ...) string
- func FilterSendCopyToEmails(logger *slog.Logger, mb *api.Mailbox, supervisor api.Supervisor, ...) []string
- func GetAbsoluteMaildirPath(defaultMailStorePath string, mb *api.Mailbox) string
- func GetSendCopyTo(logger *slog.Logger, fromMailerDaemon bool, mb *api.Mailbox, ...) (sendCopiesTo []string)
- func HaveCapacity(mb *api.Mailbox, needCapacity int64) bool
- func IsBlacklisted(mb *api.Mailbox, asciiEmailLowerCase string) bool
- func IsRejectErr(err error) bool
- func IsWhitelisted(mb *api.Mailbox, asciiEmailLowerCase string) bool
- func MimeHeadersSliceToString(headers []string) string
- func MimeHeadersSliceToStringLength(headers []string, maxLength int) string
- func MimeHeadersToString(h textproto.MIMEHeader) string
- func MimeHeadersToStringWithOrder(h textproto.MIMEHeader, order []string) string
- func NewFileFromMailboxDelivery(proxy MessageReceiverProxy, delivery Delivery, hostName string, ...) (filename string, dataSize int64, err error)
- func NewPostmasterAddressEmail()
- func NewRejectErr(code RejectErrCode) error
- func NewRejectErrMessage(code RejectErrCode, message string) error
- func OpenFile(filename string, flag int, perms os.FileMode) (f *os.File, err error)
- func RegisterCommand(name string, cmd CommandHandler)
- func RejectCodeToMessage(code RejectErrCode) string
- func RejectCodeToMessageWithMyMessage(code RejectErrCode, appendMessage string) string
- func SendAllRequiredCopies(logger *slog.Logger, fromMailerDaemon bool, originalRecipient string, ...)
- func SendAutoresponseMessage(logger *slog.Logger, msg *mail.Message, mb *api.Mailbox, d *Delivery) (string, *mimemsg.Message)
- func StoreMessage(appendBytes []byte, proxy MessageReceiverProxy, delivery Delivery, ...) (fileSize int64, err error)
- func StoreMessageFromWriter(appendBytes []byte, wrto io.WriterTo, filename string) (fileSize int64, err error)
- func TryOpenFile(filename string, howManyTries int, sleepStep time.Duration, flag int, ...) (f *os.File, err error)
- func ValidEmail(value string) api.Maybe
- func WrapText(w io.Writer, text string, newline, indent, preIndent string, width int)
- type AddressEmail
- type AuthorizationHandler
- type Client
- func (c *Client) AuthLoginGetPassword(cmd string)
- func (c *Client) AuthLoginGetUsername(cmd string)
- func (c *Client) AuthMe(username, password string) bool
- func (c *Client) Cmd(expectCode int, format string, args ...interface{}) (int, string, error)
- func (c *Client) DidHelo() bool
- func (c *Client) DidMailFrom() bool
- func (c *Client) DidRecipient() bool
- func (c *Client) GetHello() string
- func (c *Client) GetInfo() ConnectionInfo
- func (c *Client) GetPassword() string
- func (c *Client) GetSession() Session
- func (c *Client) GetUsername() string
- func (c *Client) IsLoggedIn() bool
- func (c *Client) ReadLine() (string, error)
- func (c *Client) UnknownCommand(cmd string, msg string)
- func (c *Client) WriteCmd(s string) (err error)
- type CommandHandler
- type Connection
- type ConnectionInfo
- type ConnectionState
- type Decision
- type Delivery
- func (d *Delivery) Close()
- func (d Delivery) GetHeader(msg *mail.Message, name string) string
- func (d *Delivery) HeaderContainsPattern(msg *mail.Message, names []string, patterns ...string) bool
- func (d Delivery) HeaderToString() string
- func (d *Delivery) HeaderValues(msg *mail.Message, key string) (ret []string)
- func (d *Delivery) MatchHeader(msg *mail.Message, name string, matcher func(value string) bool) bool
- func (d *Delivery) SpoolDir(basePath string) string
- type DeliveryProxy
- type EmailAddressType
- type ImapFlag
- type Listener
- func NewDefaultListener() *Listener
- func NewDefaultListenerExt(address, reverseHostname string, flags bitmask.Flag64) *Listener
- func NewDefaultListenerWithAddress(address string) *Listener
- func NewListener(address string, maxErrorsPerConnection int, maxConnections int, ...) *Listener
- func NewLmtp(hostname string) *Listener
- type Maildir
- type MessageReceiver
- func (mr *MessageReceiver) AcceptData(ctx context.Context, c *Client, r io.Reader) (err error)
- func (mr *MessageReceiver) AcceptRecipient(currentHostname string, from, to AddressEmail, client *Client) bool
- func (mr *MessageReceiver) ArrivalTime() time.Time
- func (mr *MessageReceiver) Close()
- func (mr *MessageReceiver) GetBodyOffset() int64
- func (mr *MessageReceiver) GetBuffer() *filebuf.Buf
- func (mr *MessageReceiver) GetMessage() *mail.Message
- func (mr *MessageReceiver) InitialMessageSize() int
- func (mr *MessageReceiver) MoveBufferPosToMessageStartLine() error
- func (mr *MessageReceiver) MoveBufferPosToStart() error
- func (mr *MessageReceiver) RecipientsCount() int
- func (mr *MessageReceiver) SeekMessage(client *Client, offset int64, whence int) bool
- func (mr *MessageReceiver) SeekMessageToBeginning(client *Client) bool
- func (mr *MessageReceiver) SeekMessageToBody(client *Client) bool
- func (mr *MessageReceiver) ToAllEmails() []AddressEmail
- func (mr *MessageReceiver) ToAllEmailsAsString() []string
- type MessageReceiverProxy
- type Metrics
- type PostmasterHolder
- type RejectBehaviour
- type RejectErr
- type RejectErrCode
- type Session
- type State
- type Super
- type SupervisorExt
Constants ¶
const ( OkResponse = "250 OK" OkResponseFmt = "250 OK %s" )
const ( // Dunno I don't know what to do or I don't want to decide, // let the next person in the chain make that decision // this should be the default answer, which does not confirm anything, // it only informs that we are moving to the next stage Dunno Decision = "dunno" // Accept we finish the entire operation and confirm; other mechanisms after this are not important // (they will not be checked) if you want to confirm the correctness of the operation, // you should return dunno accept only finally Accept = "accept" // Reject rejection, we do not proceed Reject = "reject" )
const ( DefaultMaxErrorPerConnection = 5 DefaultMaxConnections = 1000 DefaultAddress = "localhost:1025" // DefaultProtocolTimeoutSec How many seconds do we wait for a command to be issued from the client DefaultProtocolTimeoutSec = 8 // DefaultDataStartReceivingTimeoutSec How many seconds do we wait for the start of data transmission // (just after receiving the data command DefaultDataStartReceivingTimeoutSec = 10 // DefaultDataReceivingTimeoutSec How many seconds do we wait for data after the data command DefaultDataReceivingTimeoutSec = 10 // 5 * 60 )
const ( DefaultListenerNameFormat = "Super %s" DefaultListenerVersion = "1.0.0" DefaultListenerMaxMessageSizeInMB = 25 DefaultListenerMaxMessageSizeInBytes = DefaultListenerMaxMessageSizeInMB * (1024 * 1024 * 1024) DefaultListenerMaxRecipientsPerMessage = 100 )
const ( FromField = "from" ToField = "to" MessageUidField = "mid" // to the public? // safe to pass on to an outsider (user police, etc.) ForPublicField = "pub" // action name ActionNameField = "action" // if the value was parried, give me the original so you know what was the reason OriginalValue = "original" ListenAddress = "listenAddress" // state of message rejected|queued DeliveryStatusField = "deliveryStatus" DeliveryRejected = "rejected" DeliveryQueued = "queued" // when we have specified what parameter and limit determines its limit, // and has its value that the user has provided LimitField = "limit" HasField = "has" )
const ( Inbox Maildir = "" Spam = ".SPAM" Sent = ".Sent" Draft = ".Draft" Trash = ".Trash" Archive = ".Archive" Custom = "$custom" )
Special folders start with a dollar
const ( ImapFlagSeen = "\\Seen" ImapFlagAnswered = "\\Answered" ImapFlagFlagged = "\\Flagged" ImapFlagDeleted = "\\Delete" ImapFlagDraft = "\\Draft" )
const ( PrivateHeader = iota AllHeaders MailHeader )
const ( // 64 flags // Authorization support Authorization bitmask.Flag64 = 1 << iota // 1 << 0 which is 00000001 StartTls // 1 << 1 which is 00000010 // Receive emails from local users ReceiveFromLocalUsers // 1 << 2 which is 00000100 // Receive emails from remote (not logged in) users ReceiveFromRemoteUsers AllowLocalhostConnection // As mandated by RFC5321 Section 4.5.5, DSNs MUST be sent with a NULL Return-Path (or MAIL FROM) sender. // The From: header MAILER-DAEMON@example.com is set by the receiving MTA, based on the NULL sender address. // czyli domyślnie zezwalamy na puste maile i uwaga jeżeli je przyjmiesz nie możesz ich odrzucić ReceiveFromNullSender RequireLocalHostAuthorization // we ignore many errors, e.g. wrong sender, etc // then check the SMTP already LmtpService )
const ( DefaultFolderPerm os.FileMode = 0700 DefaultFilePerm os.FileMode = 0640 )
const DecisionKey = "response"
const XForwardedToHeader = "X-Forwarded-To"
It means that we have already sent a message from this email and if it is again send a copy to then in this case we ignore the subsequent sending of the copy
Variables ¶
var Commands = make(map[string]CommandHandler)
var NativeEndian binary.ByteOrder
var RegisteredCommands []string
RegisteredCommands preserves the order - which makes it possible to find an error
Functions ¶
func AllowAuthorize ¶
func CheckErrorsCount ¶
CheckErrorsCount check the number of errors and end the connection if necessary
func DefaultNewFileFromDelivery ¶
func DefaultNewFileFromDelivery(proxy MessageReceiverProxy, delivery Delivery, hostName string, baseStoragePath string) (filename string, dataSize int64, err error)
DefaultNewFileFromDelivery Default function to save the message to disk
func DeliveryAddHeaderAs ¶
func DeliveryDelHeader ¶
func DovecotMessageFilenameV2 ¶
func DovecotMessageFilenameV2(delivery *Delivery, proxy MessageReceiverProxy, hostname string, finalFileSize int) string
DovecotMessageFilenameV2 Dovecot compatible file name generator V2 that's because at the end :2,
https://wiki2.dovecot.org/MailboxFormat/Maildir About locks, files should always land in new, otherwise there may be problems, e.g. loss of messages when performing imap operations Delivering mails to new/ directory doesn't have any problems, so there's no need for LDAs to support any type of locking.
https://cr.yp.to/proto/maildir.html When you move a file from new to cur, you have to change its name from uniq to uniq:info. Make sure to preserve the uniq string, so that separate messages can't bump into each other. info is morally equivalent to the Status field used by mbox readers. It'd be useful to have MUAs agree on the meaning of info, so I'm keeping a list of info semantics. Here it is.
info starting with "1,": Experimental semantics.
info starting with "2,": Each character after the comma is an independent flag.
Flag "P" (passed): the user has resent/forwarded/bounced this message to someone else. Flag "R" (replied): the user has replied to this message. Flag "S" (seen): the user has viewed this message, though perhaps he didn't read all the way through it. Flag "T" (trashed): the user has moved this message to the trash; the trash will be emptied by a later user action. Flag "D" (draft): the user considers this message a draft; toggled at user discretion. Flag "F" (flagged): user-defined flag; toggled at user discretion. New flags may be defined later. Flags must be stored in ASCII order: e.g., "2,FRS".
func FilterSendCopyToEmails ¶
func FilterSendCopyToEmails(logger *slog.Logger, mb *api.Mailbox, supervisor api.Supervisor, allowToHandler func(lowerAsciiEmailAddress string) bool) []string
FilterSendCopyToEmails Filters email addresses Send-Copies to returns unique email addresses that you can send forward are supported by us or we've given you the green light to send to them from the machine
func GetAbsoluteMaildirPath ¶
GetAbsoluteMaildirPath build maildir path prefix @defaultMailStorePath is default startpath prefix, if mb.MountPath is not empty it overwrite defaultMailStorePath
func GetSendCopyTo ¶
func GetSendCopyTo(logger *slog.Logger, fromMailerDaemon bool, mb *api.Mailbox, delivery *Delivery, proxy MessageReceiverProxy, supervisor api.Supervisor) (sendCopiesTo []string)
func HaveCapacity ¶
HaveCapacity whether we will fit a message about the size of the @needCapacity in the user's account
func IsBlacklisted ¶
IsBlacklisted Whether the @asciiEmailLowerCase is marked as a white sender
func IsRejectErr ¶
func IsWhitelisted ¶
IsWhitelisted Whether the @asciiEmailLowerCase is marked as a white sender
func MimeHeadersSliceToString ¶
it doesn't really matter
func MimeHeadersToString ¶
func MimeHeadersToString(h textproto.MIMEHeader) string
it doesn't really matter
func MimeHeadersToStringWithOrder ¶
func MimeHeadersToStringWithOrder(h textproto.MIMEHeader, order []string) string
func NewPostmasterAddressEmail ¶
func NewPostmasterAddressEmail()
func NewRejectErr ¶
func NewRejectErr(code RejectErrCode) error
func NewRejectErrMessage ¶
func NewRejectErrMessage(code RejectErrCode, message string) error
func RegisterCommand ¶
func RegisterCommand(name string, cmd CommandHandler)
func RejectCodeToMessage ¶
func RejectCodeToMessage(code RejectErrCode) string
func RejectCodeToMessageWithMyMessage ¶
func RejectCodeToMessageWithMyMessage(code RejectErrCode, appendMessage string) string
func SendAllRequiredCopies ¶
func SendAllRequiredCopies(logger *slog.Logger, fromMailerDaemon bool, originalRecipient string, mb *api.Mailbox, d *Delivery, proxy MessageReceiverProxy, supervisor api.MaildirSupervisor)
func SendAutoresponseMessage ¶
func StoreMessage ¶
func StoreMessage(appendBytes []byte, proxy MessageReceiverProxy, delivery Delivery, filename string) (fileSize int64, err error)
StoreMessage file to remember that the folder you are saving to must have already been created by you,
so you need to create it yourself before calling this function
@filename the full save path
func StoreMessageFromWriter ¶
func TryOpenFile ¶
func ValidEmail ¶
func WrapText ¶
WrapText prepares comment text for presentation in textual output. It wraps paragraphs of text to width or fewer Unicode code points and then prefixes each line with the indent. In preformatted sections (such as program text), it prefixes each non-blank line with preIndent. newline - lamacz lini
Types ¶
type AddressEmail ¶
func NewAddressEmail ¶
func NewAddressEmail(username, host string) AddressEmail
func NewAddressEmailSanitize ¶
func NewAddressEmailSanitize(value string) (AddressEmail, bool)
func SanitizeEmailAddress ¶
func SanitizeEmailAddress(value string) AddressEmail
func (AddressEmail) IsEmpty ¶
func (a AddressEmail) IsEmpty() bool
func (AddressEmail) IsEqual ¶
func (a AddressEmail) IsEqual(another AddressEmail) bool
func (AddressEmail) IsValid ¶
func (a AddressEmail) IsValid() bool
func (AddressEmail) String ¶
func (e AddressEmail) String() string
type AuthorizationHandler ¶
type Client ¶
type Client struct { // current customer number at the time of connection CurrentClientNo int32 WhenConnected time.Time // Listener *LocalSmtpServer Helo string ListenerReverseHostname string ListenerAppName string Flags bitmask.Flag64 DidStartTlsNotAllowed bool UseEhlo bool DidHeloCmd bool WeClose bool Username string Password string RejectInfo []string MaxErrorsPerConnection int MaxRecipientsPerMessage int MaxMessageSizeInBytes int64 // copy of listener.DataStartReceivingTimeoutDuration DataStartReceivingTimeoutDuration time.Duration // copy of listener.DataStartReceivingTimeoutDuration because we set it after each data reception ProtocolTimeoutDuration time.Duration Con net.Conn Text *textproto.Conn ErrorsCount int Session Session Info ConnectionInfo // contains filtered or unexported fields }
func (*Client) AuthLoginGetPassword ¶
func (*Client) AuthLoginGetUsername ¶
func (*Client) DidMailFrom ¶
func (*Client) DidRecipient ¶
func (*Client) GetInfo ¶
func (c *Client) GetInfo() ConnectionInfo
func (*Client) GetPassword ¶
func (*Client) GetSession ¶
func (*Client) GetUsername ¶
func (*Client) IsLoggedIn ¶
func (*Client) UnknownCommand ¶
type CommandHandler ¶
type CommandHandler func(c *Client, supervisor api.Supervisor, args string)
type Connection ¶
type Connection interface { GetInfo() ConnectionInfo GetHello() string GetUsername() string GetPassword() string }
type ConnectionInfo ¶
type ConnectionInfo struct { StartConnection time.Time Flags bitmask.Flag64 // instance no InstanceId int // another customer number since launch Id int64 // it should be unique in the long run UUId string LocalAddr string RemoteAddr string ReverseHostName string }
func NewConnectionInfo ¶
func NewConnectionInfo(id int64, flags bitmask.Flag64) ConnectionInfo
type ConnectionState ¶
type ConnectionState struct {
// contains filtered or unexported fields
}
func NewConnectionState ¶
func NewConnectionState(flags bitmask.Flag64) ConnectionState
NewConnectionState As mandated by RFC5321 Section 4.5.5, DSNs MUST be sent with a NULL Return-Path (or MAIL FROM) sender. The From: header MAILER-DAEMON@example.com is set by the receiving MTA, based on the NULL sender address.
func (ConnectionState) Close ¶
func (mp ConnectionState) Close()
Close If you have any pointers, remove them and close all streams
type Delivery ¶
type Delivery struct { // another message number from the moment the application was launched MessageNo uint32 // unique id of this message UniqueId string From AddressEmail To AddressEmail // where to deliver, to which folder on disk Mailbox Maildir // If mailbox = Custom, here is its physical name. // If you want to filter mail independently based on folders, // set Mailbox = Custom in CustomMailbox = ".Notifications" // like in gmail CustomMailbox string Flags ImapFlag // if true, it will be placed in the "${MAILBOX}/new" folder, // otherwise in "${MAILBOX}/cur" // do not confuse it with the //Recent flag, which should not be used in ImapFlags // because it is a session flag assigned by the IMAP server at the session opening level ( RFC3501 ) IsRecent bool // When the message was forwarded IsPassed bool // contains filtered or unexported fields }
func CloneDelivery ¶
CloneDelivery cloning delivery of the same message, but to a different mailbox
func NewDelivery ¶
func NewDelivery(from, to AddressEmail) Delivery
func NewDeliveryFromClient ¶
func NewDeliveryFromClient(client Connection, from, to AddressEmail) Delivery
func (Delivery) GetHeader ¶
GetHeader get the first header on the list, if we have an appendHeader, we return them - because they are priority, otherwise we return those from the email
func (*Delivery) HeaderContainsPattern ¶
func (Delivery) HeaderToString ¶
func (*Delivery) HeaderValues ¶
HeaderValues get the first priority headers on the list and then the rest of the message
func (*Delivery) MatchHeader ¶
type DeliveryProxy ¶
type EmailAddressType ¶
type EmailAddressType int
type Listener ¶
type Listener struct { MaxConnections int // MaxMessageSizeInBytes int MaxErrorsPerConnection int MaxRecipientsPerMessage int MaxMessageSizeInBytes int64 ProtocolTimeoutDuration time.Duration DataReceivingTimeoutDuration time.Duration DataStartReceivingTimeoutDuration time.Duration // contains filtered or unexported fields }
func NewDefaultListener ¶
func NewDefaultListener() *Listener
func NewDefaultListenerExt ¶
NewDefaultListenerExt Mainly for the needs of testing, but also for simple customers
func NewListener ¶
func (*Listener) Run ¶
func (l *Listener) Run(ctx context.Context, supervisor SupervisorExt, cancelFunc context.CancelFunc) error
type Maildir ¶
type Maildir string
mailbox i.e. the directory to which to move mail after receiving it
func ToMailDir ¶
because adding headers would make us add to the message the headers already received in the previous session
func NewMessageDeliveryFrom(delivery Delivery, appendHeaders textproto.MIMEHeader, emailLowerAsciiString string) Delivery { // delivery.SetHeader(headers.DeliveredTo, emailLowerAsciiString) //delivery.To = SanitizeEmailAddress(emailLowerAsciiString) delivery.Maildir = ToMailDir(emailLowerAsciiString) delivery.appendHeader = textproto.MIMEHeader{} for k, v := range appendHeaders { delivery.appendHeader[k] = v } return delivery }
type MessageReceiver ¶
type MessageReceiver struct {
// contains filtered or unexported fields
}
func NewMessageReceiver ¶
func NewMessageReceiver() MessageReceiver
func (*MessageReceiver) AcceptData ¶
func (*MessageReceiver) AcceptRecipient ¶
func (mr *MessageReceiver) AcceptRecipient(currentHostname string, from, to AddressEmail, client *Client) bool
func (*MessageReceiver) ArrivalTime ¶
func (mr *MessageReceiver) ArrivalTime() time.Time
func (*MessageReceiver) GetBodyOffset ¶
func (mr *MessageReceiver) GetBodyOffset() int64
func (*MessageReceiver) GetBuffer ¶
func (mr *MessageReceiver) GetBuffer() *filebuf.Buf
func (*MessageReceiver) GetMessage ¶
func (mr *MessageReceiver) GetMessage() *mail.Message
func (*MessageReceiver) InitialMessageSize ¶
func (mr *MessageReceiver) InitialMessageSize() int
InitialMessageSize The size of the message right after downloading, without the extra headers you created
func (*MessageReceiver) MoveBufferPosToMessageStartLine ¶
func (mr *MessageReceiver) MoveBufferPosToMessageStartLine() error
MoveBufferPosToMessageStartLine move to the beginning of the line where the message begins
func (*MessageReceiver) MoveBufferPosToStart ¶
func (mr *MessageReceiver) MoveBufferPosToStart() error
MoveBufferPosToStart move to the beginning of the file
func (*MessageReceiver) RecipientsCount ¶
func (mr *MessageReceiver) RecipientsCount() int
func (*MessageReceiver) SeekMessage ¶
func (mr *MessageReceiver) SeekMessage(client *Client, offset int64, whence int) bool
func (*MessageReceiver) SeekMessageToBeginning ¶
func (mr *MessageReceiver) SeekMessageToBeginning(client *Client) bool
func (*MessageReceiver) SeekMessageToBody ¶
func (mr *MessageReceiver) SeekMessageToBody(client *Client) bool
func (*MessageReceiver) ToAllEmails ¶
func (mr *MessageReceiver) ToAllEmails() []AddressEmail
func (*MessageReceiver) ToAllEmailsAsString ¶
func (mr *MessageReceiver) ToAllEmailsAsString() []string
type MessageReceiverProxy ¶
type Metrics ¶
type Metrics struct {
// contains filtered or unexported fields
}
The needs of the program used should not be typical metrics, they are data that are intended to speed up the program's operation e.g. for Prometheus
func (*Metrics) ClientConnected ¶
func (*Metrics) ClientDisconnected ¶
func (*Metrics) ConnectedClients ¶
type PostmasterHolder ¶
type PostmasterHolder interface {
MailerDaemonEmailAddress() string
}
type RejectBehaviour ¶
type RejectErr ¶
type RejectErr struct { Code RejectErrCode AppendMessage string CloseConnection bool }
func (RejectErr) ToMtpResponse ¶
ToMtpResponse To the replies in the servers (S|L)MTP
type RejectErrCode ¶
type RejectErrCode int
const ( // Reject should not be session-driven, should only inform about the following states: // 1 Server error TemporaryServerRejectErr RejectErrCode = iota // 2 Rejecting an email address (recipient or sender), it doesn't matter because it results from the context RecipientServerRejectErr // 3 Rejection due to message size // 4 Rejected due to lack of adequate free disk space QuotaLowRejectErr // 5 Spam rejection YouSpamerGoAwayRejectErr // 6 Rejection due to throtling TooManyConnectionsRejectErr // If the problem is temporary -- be sure to do your text TemporaryMailBoxProblemErr // Reject an attempt to send to the specified address (maybe you're a spammer, // or maybe the mailbox doesn't exist anymore) -- don't try again RecipientAddressRejectErr )
type Session ¶
type Session interface { IsLoggedIn() bool // From The address from the from header but also the login of the logged-in person (if so) From() AddressEmail MaxMessageSize() uint64 // IsAllowSendAs Can a user send a message from this address only to logged in users? IsAllowSendAs(addressEmailInAsciiLowerCase AddressEmail) (bool, error) // OnAuthorization Login authorization // @username is already IDN decoded value as lowercase ASCII // @password is plain text value received from client (we don't support anything other than plain text at this time) // @service service type // @useSsl connection use ssl OnAuthorization(username string, password string, service api.Service, useSsl api.Maybe) (bool, error) // ResetMessageReceivingStatus Consider the shipment, if any, as not yet there and will be prepared to pick up another ResetMessageReceivingStatus() error // AcceptMessageFromEmail The client wants to send us a new message, if you return an error, // you will not accept the message, // at this stage you can already check the sender of the message // because it is the actual so-called Envelope lowercase and already in ascii AcceptMessageFromEmail(senderAscii AddressEmail) error // AcceptRecipient Do you accept the recipient of this message? is already in ASCII format, // you can treat it as caching to load all mailboxes to which it will deliver the message AcceptRecipient(recipientAscii AddressEmail) error // AcceptMessage: At this stage, you need to decide whether you will accept the message to all recipients or reject // it for everyone. If you can accept only some users, the rejection will always apply to the sender, // in the sense that we do not accept from him because he is a spammer. // You can return your own message, e.g. with message tracking or a link to a website that explains the reason, AcceptMessage(message *mail.Message) error // Physically deliver the message to the user's inbox ProcessDelivery(proxy MessageReceiverProxy, delivery Delivery, revHostname string) error Close() }
Session connection session itself does not mean that the client is logged in, it should be generated by Super interface, the session works synchronously and without threads in the sense of accepting commands from the server
type Super ¶
type Super interface { // Default hostname Hostname() string // Name visible when logging in Name() string // Software number (visible reporting processes) Version() string Flags() bitmask.Flag64 // Used at the stage when we do not yet know or cannot determine the quota of the actual user DefaultMaxMessageSizeInBytes() int64 DefaultMaxRecipientsPerMessage() int }
type SupervisorExt ¶
type SupervisorExt interface { api.Supervisor api.MaildirStorage // OpenSession Opening or ending the session. // If we don't want to connect, we need to give the content to rejectMessage OpenSession(ci ConnectionInfo, l *slog.Logger) (session Session, err error) CloseSession(session Session) }
Source Files ¶
- client.go
- cmd_auth.go
- cmd_data.go
- cmd_ehlo.go
- cmd_expn.go
- cmd_helo.go
- cmd_mail.go
- cmd_nop.go
- cmd_quit.go
- cmd_rcpt.go
- cmd_rset.go
- cmd_strarttls.go
- cmd_vrfy.go
- commands.go
- connection.go
- connectionstate.go
- decision.go
- delivery.go
- dovecot.go
- emailaddress.go
- headers.go
- helpers.go
- init.go
- listener.go
- logging.go
- mailbox.go
- maildir.go
- messagereciver.go
- metrics.go
- mtp.go
- session.go
- store.go
- tryopenfile.go
- wrapper.go