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 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 ( 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 ( // Authorization 64 flags // Authorization support Authorization bitmask.Flag64 = 1 << iota // 1 << 0 which is 00000001 StartTls // 1 << 1 which is 00000010 // ReceiveFromLocalUsers Receive emails from local users ReceiveFromLocalUsers // 1 << 2 which is 00000100 // ReceiveFromRemoteUsers Receive emails from remote (not logged in) users ReceiveFromRemoteUsers AllowLocalhostConnection // ReceiveFromNullSender As mandated by RFC5321 Section 4.5.5, DSNs MUST be sent with a NULL Return-Path (or MAIL FROM) sender. // The From: header [email protected] 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 // LmtpService 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"
XForwardedToHeader 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 ¶
MimeHeadersSliceToString it doesn't really matter
func MimeHeadersToString ¶
func MimeHeadersToString(h textproto.MIMEHeader) string
MimeHeadersToString it doesn't really matter
func MimeHeadersToStringWithOrder ¶
func MimeHeadersToStringWithOrder(h textproto.MIMEHeader, order []string) string
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 [email protected] 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 Decision ¶
type Decision string
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 // todo: Accept = "accept" // Reject rejection, we do not proceed Reject = "reject" )
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
Maildir mailbox i.e. the directory to which to move mail after receiving it
func ToMailDir ¶
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
}
func (Maildir) CreateNewMailDirIfNotExists ¶
func (m Maildir) CreateNewMailDirIfNotExists(basePath string, customValue string, folderPerm, filePerm os.FileMode) (string, error)
CreateNewMailDirIfNotExists Create a folder ${MAILDIR}/new if it does not exist and return the full path where you should write
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
}
Metrics 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 ( // TemporaryServerRejectErr Reject should not be session-driven, should only inform about the following states: // 1 Server error TemporaryServerRejectErr RejectErrCode = iota // RecipientServerRejectErr 2 Rejecting an email address (recipient or sender), it doesn't matter because it results from the context RecipientServerRejectErr // QuotaLowRejectErr 3 Rejection due to message size // 4 Rejected due to lack of adequate free disk space QuotaLowRejectErr // YouSpamerGoAwayRejectErr 5 Spam rejection YouSpamerGoAwayRejectErr // TooManyConnectionsRejectErr 6 Rejection due to throtling TooManyConnectionsRejectErr // TemporaryMailBoxProblemErr If the problem is temporary -- be sure to do your text TemporaryMailBoxProblemErr // RecipientAddressRejectErr 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 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
// ProcessDelivery 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 {
// Hostname Default hostname
Hostname() string
// Name visible when logging in
Name() string
// Version Software number (visible reporting processes)
Version() string
Flags() bitmask.Flag64
// DefaultMaxMessageSizeInBytes 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