SmtpSession final class
Minn\Mail\SmtpSession · public/minn/src/Minn/Mail/SmtpSession.php · 461 lines
One SMTP conversation as the reference's client holds it: the socket, the last reply, the server's extensions from EHLO, and the last error as {error, detail, smtp_code, smtp_code_ex}. Every command names itself in its error ("RCPT TO command failed"); a command sent before connecting fails as "Called X without being connected". Debug text goes to the given closure with its level: 1 client lines, 2 server replies, 3 connection events, 4 raw inbound lines. Credentials never reach it.
Constants and properties
| const | MAX_LINE = 998 | |
| private | CREDENTIALS = array ( 0 => 'User & Password', 1 => 'Username', 2 => 'Password', ) | |
| private | AUTH_ORDER = array ( 0 => 'CRAM-MD5', 1 => 'LOGIN', 2 => 'PLAIN', 3 => 'XOAUTH2', ) | |
| private | TRANSACTION_IDS = array ( 0 => '/queued as ([^\\s]+)/i', 1 => '/\\bOK id=([^\\s]+)/i', 2 => '/^\\d{3} 2\\.0\\.0 ([^\\s]+) Message accepted for delivery/m', 3 => '/^\\d{3} 2\\.\\d\\.0 <?([^\\s@>]+)@[^\\s]* Queued mail for delivery/m', 4 => '/Message Queued \\(([^)]+)\\)/i', 5 => '/^\\d{3} Ok ([^\\s]+)/m', ) | |
| private | mixed $socket | |
| private | array $error | |
| private | string $heloReply | |
| private | ?array $caps | |
| private | string $lastReply | |
| private | string|false|null $transactionId | |
| private | int $timeout | |
| private | int $timelimit | |
| private | readonly Closure $debug | Promoted from the constructor. |
Public
| new | __construct(Closure $debug)# |
| ||||||
| method | limits(int $timeout, int $timelimit): void# | How long one read may wait and how long a whole reply may take, in seconds. | ||||||
| method | connect(string $host, ?int $port, int $timeout, array $options): bool# | Opens the connection and reads the greeting.
| ||||||
| method | startTls(): bool# | Asks for TLS and turns it on. | ||||||
| method | authenticate(string $user, string $password, string $type, ?string $oauth): bool# | Signs in with the named mechanism, or the strongest the server offers when it is empty or not offered.
| ||||||
| method | connected(): bool# | Whether the connection is open; a socket closed at the far end is closed here too. | ||||||
| method | close(): void# | Closes the socket and forgets the server's greeting and extensions; the last error stays. | ||||||
| method | data(string $message): bool# | Sends a message: DATA, the lines (a line past 998 characters split at its last space, or at 997 without one; header continuations indented; leading dots doubled), then the closing dot. | ||||||
| method | hello(string $host): bool# | EHLO, falling back to HELO; the extensions come from the EHLO reply. | ||||||
| method | mail(string $from, string $parameters): bool# | MAIL FROM, with the given parameters (" XVERP", " SMTPUTF8") after the address. | ||||||
| method | quit(string $onError = 'close'): bool# | QUIT; the connection closes when it succeeds, or anyway unless told to keep it. | ||||||
| method | recipient(string $address, string $dsn): bool# | RCPT TO, with the delivery notifications asked for (NEVER, SUCCESS, FAILURE, DELAY). | ||||||
| method | xclient(array $vars, array $allowed): bool# | XCLIENT with the named attributes that are in $allowed; others are dropped.
| ||||||
| method | turn(): bool# | TURN is refused here, as the reference refuses it. | ||||||
| method | command(string $name, string $line, array $expect): bool# | Sends one command and reads the reply; a reply outside $expect fails with "{name} command failed" and the reply's detail and codes.
| ||||||
| method | send(string $data, string $command): int|false# | Writes raw text to the server; credential commands show as hidden in the debug text. | ||||||
| method | error(): array# | The last error; every field is empty after a command that succeeded. @return array{error: string, detail: string, smtp_code: int|string, smtp_code_ex: string} | ||||||
| method | extensions(): ?array# | The extensions from the last EHLO (or the HELO greeting), null before one. @return array<string, mixed>|null | ||||||
| method | extension(string $name): mixed# | One extension's value: true for a bare one, a string or list for one with arguments, false when absent, null before EHLO. | ||||||
| method | lastReply(): string# | The server's last reply, every line. | ||||||
| method | transactionId(): string|false|null# | The queue id the server gave the last message: null before one was sent, false when none was recognised. | ||||||
| static | parseReply(string $reply): array# | The reply's code, enhanced code (when present) and the text after them. @return array{0: int, 1: string, 2: string} |
Internals 9
Private and protected methods: how the class does its work. Not a contract; they change whenever the code is tidied.
| private | greet(string $verb, string $host): bool# | ||||
| private | extensionsFrom(string $verb, string $reply): array# | @return array<string, mixed> | |||
| private | mechanism(string $type, ?string $oauth): string# | ||||
| private | unsupported(string $type): bool# | ||||
| private | open(string $host, int $port, int $timeout, array $options)# |
| |||
| private | lines(): string# | ||||
| private | failed(int $no, string $text, string $file, int $line): bool# | ||||
| private | setError(string $message, string $detail = '', string|int $code = '', string $codeEx = ''): void# | ||||
| private | say(string $text, int $level): void# |
Nothing matches.