### msmtp Configuration File Example Source: https://github.com/marlam/msmtp/blob/master/_autodocs/README.md This example shows a typical msmtp configuration file (`~/.msmtprc`) setup. It defines default settings, a specific Gmail account with authentication details, and sets the Gmail account as the default. The password is managed securely using `gpg`. ```ini # ~/.msmtprc defaults port 587 tls on account gmail host smtp.gmail.com from user@gmail.com auth on user user@gmail.com passwordeval gpg -d ~/.msmtp-password.gpg account default : gmail ``` -------------------------------- ### Complete TLS Connection Example Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/tls.md Demonstrates the full lifecycle of establishing a TLS connection for SMTP, including library initialization, socket connection, TLS configuration, handshake, and cleanup. This example is suitable for understanding the overall flow of secure email transmission setup. ```c #include "mtls.h" #include "net.h" #include "readbuf.h" #include int main(void) { mtls_t tls; int fd = -1; char *errstr = NULL; // Initialize if (net_lib_init(&errstr) != NET_EOK) { fprintf(stderr, "Net init failed: %s\n", errstr); free(errstr); return 1; } if (mtls_lib_init(&errstr) != TLS_EOK) { fprintf(stderr, "TLS init failed: %s\n", errstr); free(errstr); net_lib_deinit(); return 1; } // Connect plain socket if (net_open_socket(NULL, NULL, -1, "smtp.example.com", 465, NULL, 30, &fd, NULL, NULL, &errstr) != NET_EOK) { fprintf(stderr, "Connection failed: %s\n", errstr); free(errstr); mtls_lib_deinit(); net_lib_deinit(); return 1; } // Configure TLS mtls_clear(&tls); if (mtls_init(&tls, NULL, NULL, NULL, "/etc/ssl/certs/ca-certificates.crt", NULL, NULL, NULL, NULL, -1, NULL, "smtp.example.com", 0, &errstr) != TLS_EOK) { fprintf(stderr, "TLS init failed: %s\n", errstr); free(errstr); close(fd); mtls_lib_deinit(); net_lib_deinit(); return 1; } // Perform handshake mtls_cert_info_t *cert_info = mtls_cert_info_new(); char *tls_desc = NULL; if (mtls_start(&tls, fd, cert_info, &tls_desc, &errstr) != TLS_EOK) { fprintf(stderr, "Handshake failed: %s\n", errstr); free(errstr); mtls_cert_info_free(cert_info); close(fd); mtls_lib_deinit(); net_lib_deinit(); return 1; } printf("TLS active: %d\n", mtls_is_active(&tls)); mtls_print_info(tls_desc, cert_info); // Use TLS connection... // mtls_gets(), mtls_puts(), etc. // Cleanup mtls_close(&tls); mtls_cert_info_free(cert_info); free(tls_desc); close(fd); mtls_lib_deinit(); net_lib_deinit(); return 0; } ``` -------------------------------- ### Aliases File Format Example Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Illustrates the expected format for an aliases file, showing how to define aliases with comments and multiple recipients. ```text # Comments start with # recipient1: alias1, alias2 recipient2: user@example.com, another@example.org ``` -------------------------------- ### Example Usage of create_msgid Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Shows how to generate a message ID using provided host, domain, and envelope sender information, and then prints it. ```c char *msgid = create_msgid("myhost", "example.com", "user@example.com"); printf("Message-ID: <%s>\n", msgid); free(msgid); ``` -------------------------------- ### Configuration with Environment Variables Source: https://github.com/marlam/msmtp/blob/master/_autodocs/configuration.md This example shows how msmtp can utilize environment variables like $USER and $HOSTNAME within the configuration file for dynamic settings. ```msmtp account gmail host smtp.gmail.com from ${USER}@gmail.com user ${USER}@gmail.com passwordeval gpg -d ~/.msmtp-${HOSTNAME}.gpg ``` -------------------------------- ### Example Usage of password_get Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Demonstrates how to call password_get to retrieve a password for a given host and user, with options to consult .netrc and prompt via TTY. Includes basic error checking and memory management. ```c char *pwd = password_get("smtp.example.com", "user", password_service_smtp, 1, 1); if (pwd) { // use password free(pwd); } ``` -------------------------------- ### Complete SMTP Client Usage Example Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Demonstrates the full workflow of an SMTP client, including network initialization, connection, authentication, sending mail, and cleanup. Requires including "smtp.h", "net.h", and "list.h". ```c #include "smtp.h" #include "net.h" #include "list.h" #include int main(void) { smtp_server_t srv; list_t *recipients; list_t *msg = NULL; char *errstr = NULL; FILE *mail_file; long mailsize = 0; int ret; // Initialize networking if (net_lib_init(&errstr) != NET_EOK) { fprintf(stderr, "Network init failed: %s\n", errstr); return 1; } // Create SMTP connection object srv = smtp_new(NULL, SMTP_PROTO_SMTP); // Connect to SMTP server ret = smtp_connect(&srv, NULL, NULL, 0, "smtp.example.com", 587, NULL, 30, NULL, NULL, &errstr); if (ret != NET_EOK) { fprintf(stderr, "Connection failed: %s\n", errstr); free(errstr); return 1; } // Get greeting and initialize session if (smtp_get_greeting(&srv, &msg, NULL, &errstr) != SMTP_EOK) { fprintf(stderr, "Greeting failed: %s\n", errstr); free(errstr); smtp_close(&srv); return 1; } list_free(msg); if (smtp_init(&srv, "localhost", &msg, &errstr) != SMTP_EOK) { fprintf(stderr, "Init failed: %s\n", errstr); free(errstr); smtp_close(&srv); return 1; } list_free(msg); // Authenticate if (smtp_auth(&srv, "smtp.example.com", 587, "user@example.com", "password", NULL, "", NULL, &msg, &errstr) != SMTP_EOK) { fprintf(stderr, "Auth failed: %s\n", errstr); free(errstr); smtp_close(&srv); return 1; } list_free(msg); // Prepare recipients recipients = list_new(); list_insert(list_last(recipients), "alice@example.com"); // Send envelope if (smtp_send_envelope(&srv, "sender@example.com", recipients, NULL, NULL, &msg, &errstr) != SMTP_EOK) { fprintf(stderr, "Envelope failed: %s\n", errstr); free(errstr); list_xfree(recipients, free); smtp_close(&srv); return 1; } list_free(msg); // Send mail content mail_file = fopen("mail.txt", "r"); if (smtp_send_mail(&srv, mail_file, 1, 1, 1, 0, &mailsize, &errstr) != SMTP_EOK) { fprintf(stderr, "Send failed: %s\n", errstr); free(errstr); fclose(mail_file); list_xfree(recipients, free); smtp_close(&srv); return 1; } fclose(mail_file); // End mail transmission if (smtp_end_mail(&srv, &msg, &errstr) != SMTP_EOK) { fprintf(stderr, "End mail failed: %s\n", errstr); free(errstr); list_xfree(recipients, free); smtp_close(&srv); return 1; } list_free(msg); // Cleanup list_xfree(recipients, free); smtp_quit(&srv, NULL); smtp_close(&srv); net_lib_deinit(); return 0; } ``` -------------------------------- ### Complete Networking Example Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/networking.md Demonstrates a full cycle of network operations: initializing the library, connecting to an SMTP server, sending an EHLO command, and reading responses. Ensure network library initialization and deinitialization are handled correctly. ```c #include "net.h" #include "readbuf.h" #include #include #include int main(void) { int fd = -1; char *errstr = NULL; readbuf_t readbuf; char line[1024]; size_t len = 0; // Initialize networking if (net_lib_init(&errstr) != NET_EOK) { fprintf(stderr, "Network init failed: %s\n", errstr); free(errstr); return 1; } // Open socket to SMTP server if (net_open_socket(NULL, NULL, -1, "smtp.example.com", 587, NULL, 30, &fd, NULL, NULL, &errstr) != NET_EOK) { fprintf(stderr, "Connection failed: %s\n", errstr); free(errstr); net_lib_deinit(); return 1; } // Read greeting readbuf_init(&readbuf); if (net_gets(fd, &readbuf, line, sizeof(line), &len, &errstr) != NET_EOK) { fprintf(stderr, "Read failed: %s\n", errstr); free(errstr); close(fd); net_lib_deinit(); return 1; } printf("Server greeting: %s", line); // Send EHLO const char *cmd = "EHLO localhost\r\n"; if (net_puts(fd, cmd, strlen(cmd), &errstr) != NET_EOK) { fprintf(stderr, "Write failed: %s\n", errstr); free(errstr); close(fd); net_lib_deinit(); return 1; } // Read response if (net_gets(fd, &readbuf, line, sizeof(line), &len, &errstr) != NET_EOK) { fprintf(stderr, "Read failed: %s\n", errstr); free(errstr); close(fd); net_lib_deinit(); return 1; } printf("Server response: %s", line); // Close net_close_socket(fd); net_lib_deinit(); return 0; } ``` -------------------------------- ### Configure Account Inheritance Source: https://github.com/marlam/msmtp/blob/master/_autodocs/configuration.md This example shows how to set up multiple accounts with inheritance. The 'gmail-work' account inherits settings from the 'gmail' account, overriding specific fields. ```msmtp defaults port 587 tls on tls_starttls on tls_trust_file /etc/ssl/certs/ca-certificates.crt auth on passwordeval pass show msmtp/%h/%u account gmail host smtp.gmail.com from alice@gmail.com user alice@gmail.com account gmail-work : gmail from alice.smith@company.com user alice.smith@gmail.com account outlook host smtp-mail.outlook.com from bob@outlook.com user bob@outlook.com account default : gmail ``` -------------------------------- ### Example Usage of eval Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Demonstrates executing a command, such as decrypting a password file using 'gpg', and handling both successful output and potential errors. ```c char *pwd = NULL; char *errstr = NULL; if (eval("gpg -d ~/.msmtp-pwd.gpg", &pwd, &errstr) == 0) { printf("Password: %s\n", pwd); free(pwd); } ``` -------------------------------- ### Minimal SMTP Connection Example Source: https://github.com/marlam/msmtp/blob/master/_autodocs/README.md This C code snippet demonstrates the basic steps to initialize the network library, create a new SMTP server instance, connect to a server, and then clean up resources. It requires including the 'smtp.h' and 'net.h' headers. ```c #include "smtp.h" #include "net.h" int main(void) { smtp_server_t srv; char *errstr = NULL; net_lib_init(&errstr); srv = smtp_new(NULL, SMTP_PROTO_SMTP); smtp_connect(&srv, NULL, NULL, 0, "smtp.example.com", 587, NULL, 30, NULL, NULL, &errstr); // ... send mail ... smtp_quit(&srv, NULL); smtp_close(&srv); net_lib_deinit(); return 0; } ``` -------------------------------- ### Handle Configuration Syntax Error (CONF_ESYNTAX) Source: https://github.com/marlam/msmtp/blob/master/_autodocs/errors.md This example demonstrates handling a configuration syntax error. It calls `get_conf` and checks if the return code is `CONF_ESYNTAX`. If so, it prints the error message and advises the user to fix the configuration file syntax. ```c list_t *accounts = NULL; char *errstr = NULL; int ret = get_conf("/home/user/.msmtprc", 0, &accounts, &errstr); if (ret == CONF_ESYNTAX) { fprintf(stderr, "Config error: %s\n", errstr); // Fix config file syntax } ``` -------------------------------- ### Get Password with Options Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Retrieves a password from system keyring, .netrc file, or interactive prompt. Allows configuration for .netrc consultation and TTY-only prompting. ```c char *password_get(const char *hostname, const char *user, password_service_t service, int consult_netrc, int getpass_only_via_tty); ``` -------------------------------- ### smtp_init() Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Initializes the SMTP session by sending the EHLO/HELO command. This function must be called after connection and again after starting TLS. ```APIDOC ## smtp_init() ### Description Initialize the SMTP session by sending EHLO/HELO command. Must be called after connection and again after starting TLS. ### Method `smtp_init` ### Parameters #### Path Parameters * `srv` (smtp_server_t*) - Yes - Connected SMTP server * `ehlo_domain` (const char*) - Yes - Domain to send in EHLO command (typically "localhost" or local hostname) * `msg` (list_t**) - Yes - Output: server response lines (list of strings) * `errstr` (char**) - Yes - Output: error message on failure ### Returns - `SMTP_EOK` on success - `SMTP_EIO` — I/O error - `SMTP_EPROTO` — protocol violation - `SMTP_EINVAL` — invalid domain ### Note This function populates `srv->cap` with server capabilities. ### Example ```c list_t *msg = NULL; char *errstr = NULL; if (smtp_init(&srv, "localhost", &msg, &errstr) == SMTP_EOK) { printf("Server caps: size=%ld flags=0x%x\n", srv->cap.size, srv->cap.flags); list_free(msg); } ``` ``` -------------------------------- ### Basic SMTP Client Pattern in C Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md Demonstrates the common pattern for sending mail via SMTP using the msmtp library. This includes initialization, connection, session setup, recipient handling, mail data transmission, and cleanup. ```c #include #include #include "net.h" #include "smtp.h" #include "list.h" int send_mail(const char *host, int port, const char *from, const char *to, FILE *mail_data) { smtp_server_t srv; list_t *recipients; list_t *msg = NULL; char *errstr = NULL; int ret; // 1. Initialize if (net_lib_init(&errstr) != NET_EOK) { fprintf(stderr, "net_lib_init: %s\n", errstr); free(errstr); return 1; } // 2. Create SMTP connection object srv = smtp_new(NULL, SMTP_PROTO_SMTP); // 3. Connect to server if ((ret = smtp_connect(&srv, NULL, NULL, 0, host, port, NULL, 30, NULL, NULL, &errstr)) != NET_EOK) { fprintf(stderr, "smtp_connect: %s\n", errstr); free(errstr); smtp_close(&srv); net_lib_deinit(); return 1; } // 4. Get greeting and initialize session if ((ret = smtp_get_greeting(&srv, &msg, NULL, &errstr)) != SMTP_EOK) { fprintf(stderr, "smtp_get_greeting: %s\n", errstr); free(errstr); list_free(msg); smtp_close(&srv); net_lib_deinit(); return 1; } list_free(msg); if ((ret = smtp_init(&srv, "localhost", &msg, &errstr)) != SMTP_EOK) { fprintf(stderr, "smtp_init: %s\n", errstr); free(errstr); list_free(msg); smtp_close(&srv); net_lib_deinit(); return 1; } list_free(msg); // 5. Build recipient list recipients = list_new(); list_insert(list_last(recipients), (void *)to); // 6. Send envelope if ((ret = smtp_send_envelope(&srv, from, recipients, NULL, NULL, &msg, &errstr)) != SMTP_EOK) { fprintf(stderr, "smtp_send_envelope: %s\n", errstr); free(errstr); list_free(msg); list_free(recipients); smtp_close(&srv); net_lib_deinit(); return 1; } list_free(msg); list_free(recipients); // 7. Send mail data long size = 0; if ((ret = smtp_send_mail(&srv, mail_data, 1, 1, 1, 0, &size, &errstr)) != SMTP_EOK) { fprintf(stderr, "smtp_send_mail: %s\n", errstr); free(errstr); smtp_close(&srv); net_lib_deinit(); return 1; } // 8. End mail transmission if ((ret = smtp_end_mail(&srv, &msg, &errstr)) != SMTP_EOK) { fprintf(stderr, "smtp_end_mail: %s\n", errstr); free(errstr); list_free(msg); smtp_close(&srv); net_lib_deinit(); return 1; } printf("Mail accepted, %ld bytes transmitted\n", size); list_free(msg); // 9. Cleanup smtp_quit(&srv, NULL); smtp_close(&srv); net_lib_deinit(); return 0; } ``` -------------------------------- ### Define Email Aliases Source: https://github.com/marlam/msmtp/blob/master/_autodocs/configuration.md Example format for an aliases file, mapping alias names to recipient email addresses. ```plaintext # Each line: alias_name: address1, address2, address3 support: admin@example.com, helpdesk@example.com friends: alice@example.com, bob@example.com ``` -------------------------------- ### mtls_init() Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/tls.md Configures TLS settings before starting encryption. This function does not perform the handshake. It initializes the TLS context with various security parameters, including certificate files, fingerprints, and verification options. ```APIDOC ## mtls_init() ### Description Configures TLS settings before starting encryption. Does not perform handshake. ### Method `int mtls_init(mtls_t *mtls, const char *key_file, const char *cert_file, const char* pin, const char *trust_file, const char *crl_file, const unsigned char *sha256_fingerprint, const unsigned char *sha1_fingerprint, const unsigned char *md5_fingerprint, int min_dh_prime_bits, const char *priorities, const char *hostname, int no_certcheck, char **errstr);` ### Parameters #### Path Parameters - **mtls** (mtls_t*) - Yes - TLS context (must be cleared first) - **hostname** (const char*) - Yes - Server hostname for certificate verification - **errstr** (char**) - Yes - Output: error message on failure #### Query Parameters - **key_file** (const char*) - No - NULL - PEM file with client private key or PKCS11 URI - **cert_file** (const char*) - No - NULL - PEM file with client certificate or PKCS11 URI - **pin** (const char*) - No - NULL - PIN for PKCS11 (e.g., smartcard) access - **trust_file** (const char*) - No - NULL - PEM file with trusted CA certificates - **crl_file** (const char*) - No - NULL - PEM file with revoked certificate list - **sha256_fingerprint** (unsigned char*) - No - NULL - 32-byte expected certificate fingerprint - **sha1_fingerprint** (unsigned char*) - No - NULL - 20-byte expected certificate fingerprint (deprecated) - **md5_fingerprint** (unsigned char*) - No - NULL - 16-byte expected certificate fingerprint (deprecated) - **min_dh_prime_bits** (int) - No - -1 - Minimum Diffie-Hellman prime bits (-1 for library default) - **priorities** (const char*) - No - NULL - GnuTLS priority string (library-dependent) - **no_certcheck** (int) - No - 0 - If 1, skip all certificate verification ### Response #### Success Response (TLS_EOK) - **TLS_EOK** on success - **TLS_ELIBFAILED** — TLS library error - **TLS_EFILE** — certificate/key file not found ### Note Certificate verification works in three modes: 1. If `trust_file` is provided: verify against CA certificates 2. Else if fingerprint is provided: verify against expected fingerprint 3. Else: perform sanity checks only (if `no_certcheck`=0) ### Request Example ```c mtls_t tls; mtls_clear(&tls); char *errstr = NULL; int ret = mtls_init(&tls, NULL, // no client cert NULL, NULL, "/etc/ssl/certs/ca-certificates.crt", // trust file NULL, NULL, NULL, NULL, -1, NULL, "smtp.example.com", 0, // do verify &errstr); if (ret != TLS_EOK) { fprintf(stderr, "TLS init failed: %s\n", errstr); free(errstr); } ``` ``` -------------------------------- ### Send Mail with Authentication Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md This C code snippet shows how to authenticate with an SMTP server using provided credentials. It assumes prior connection and TLS setup. Error handling for authentication failures and insecure connections is included. ```c int send_mail_auth(const char *host, int port, const char *from, const char *to, const char *user, const char *password, FILE *mail_data) { // ... connection and TLS setup as above ... // Authenticate list_t *msg = NULL; char *errstr = NULL; int ret; if ((ret = smtp_auth(&srv, host, port, user, password, NULL, "", NULL, &msg, &errstr)) != SMTP_EOK) { if (ret == SMTP_EAUTHFAIL) { fprintf(stderr, "Authentication failed\n"); } else if (ret == SMTP_EINSECURE) { fprintf(stderr, "Auth would expose password; TLS required\n"); } else { fprintf(stderr, "smtp_auth: %s\n", errstr); } free(errstr); list_free(msg); // error handling... return 1; } list_free(msg); // Continue with mail transmission... // ... (same as basic pattern) ... } ``` -------------------------------- ### Start TLS Handshake Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/tls.md Performs the TLS handshake on an established socket connection. This function must be called after `mtls_init()`. It can optionally retrieve certificate information and a description of the TLS session parameters. ```c int mtls_start(mtls_t *mtls, int fd, mtls_cert_info_t *tci, char **mtls_parameter_description, char **errstr); ``` ```c mtls_cert_info_t *cert_info = mtls_cert_info_new(); char *tls_desc = NULL; char *errstr = NULL; int ret = mtls_start(&tls, fd, cert_info, &tls_desc, &errstr); if (ret == TLS_EOK) { printf("TLS session: %s\n", tls_desc); mtls_cert_info_free(cert_info); free(tls_desc); } else { fprintf(stderr, "TLS handshake failed: %s\n", errstr); free(errstr); mtls_cert_info_free(cert_info); } ``` -------------------------------- ### Get Canonical Hostname Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/networking.md Resolve a hostname to its fully qualified domain name (FQDN) using net_get_canonical_hostname. Pass NULL to use the local system's hostname. Remember to free the returned string. ```c char *net_get_canonical_hostname(const char *hostname); ``` ```c char *fqdn = net_get_canonical_hostname("localhost"); if (fqdn) { printf("FQDN: %s\n", fqdn); free(fqdn); } ``` -------------------------------- ### Handle TLS Certificate File Error Source: https://github.com/marlam/msmtp/blob/master/_autodocs/errors.md Handle TLS_EFILE errors, which occur when certificate or key files are not found or are unreadable. This example demonstrates checking the return value of `smtp_tls_init` and printing specific error messages. ```c char *errstr = NULL; if (smtp_tls_init(&srv, "key.pem", "cert.pem", NULL, "/etc/ssl/certs/ca-bundle.crt", NULL, NULL, NULL, NULL, -1, NULL, "smtp.example.com", 0, &errstr) != TLS_EOK) { fprintf(stderr, "TLS file error: %s\n", errstr); fprintf(stderr, "Check paths and file permissions\n"); } ``` -------------------------------- ### Account Creation and Deallocation Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md Illustrates the process of creating an account object from configuration, setting its properties, and ensuring it is properly deallocated afterwards. ```c // Create account from config account_t *acc = account_new(NULL, "myaccount"); acc->host = xstrdup("smtp.example.com"); acc->port = 587; // ... configure ... // Use account... // Free account account_free(acc); ``` -------------------------------- ### smtp_etrn() Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Sends a Remote Message Queue Starting (ETRN) request to the server as defined in RFC 1985. ```APIDOC ## smtp_etrn() ### Description Send a Remote Message Queue Starting (ETRN) request to the server (RFC 1985). ### Parameters #### Path Parameters - **srv** (smtp_server_t*) - Required - SMTP server - **etrn_argument** (const char*) - Required - Hostname to request queue flushing for - **msg** (list_t**) - Required - Output: server response lines - **errstr** (char**) - Required - Output: error message on failure ### Returns - `SMTP_EOK` on success - `SMTP_EIO` — I/O error - `SMTP_EINVAL` — invalid argument - `SMTP_EUNAVAIL` — ETRN not supported - `SMTP_EPROTO` — protocol violation ``` -------------------------------- ### Initialize and Deinitialize Network Library Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md Shows the essential steps for initializing the network library before use and deinitializing it upon completion to manage resources correctly. ```c net_lib_init(&errstr); // mtls_lib_init(&errstr); // if using TLS ``` ```c smtp_close(&srv); // mtls_lib_deinit(); // if initialized net_lib_deinit(); ``` -------------------------------- ### Get TLS Certificate Information Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/tls.md Extracts certificate information from an active TLS connection. Ensure the provided structure is allocated using mtls_cert_info_new(). ```c int mtls_cert_info_get(mtls_t *mtls, mtls_cert_info_t *tci, char **errstr); ``` -------------------------------- ### Get SMTP Server Greeting Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Reads and parses the server greeting message after establishing a connection. This is typically the first message received from the server. ```c int smtp_get_greeting(smtp_server_t *srv, list_t **errmsg, char **buf, char **errstr); ``` ```c list_t *response = NULL; char *server_id = NULL; char *errstr = NULL; if (smtp_get_greeting(&srv, &response, &server_id, &errstr) == SMTP_EOK) { printf("Server: %s\n", server_id); free(server_id); list_free(response); } ``` -------------------------------- ### Get List Tail Element Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Retrieves the last element (tail) of the list. This is often used as the insertion point for appending new elements. ```c list_insert(list_last(head), data); // insert at end ``` -------------------------------- ### Get Default Syslog Facility Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/configuration.md Retrieves the default syslog facility name used by msmtp. The returned string is allocated and must be freed by the caller. ```c char *get_default_syslog_facility(void); ``` -------------------------------- ### Configure STARTTLS Source: https://github.com/marlam/msmtp/blob/master/_autodocs/configuration.md Controls whether to use STARTTLS to upgrade the connection or initiate TLS immediately. ```plaintext tls_starttls on ``` -------------------------------- ### Create New Account Configuration Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/configuration.md Initializes a new account_t structure with default values. The returned pointer must be freed using account_free(). ```c account_t *acc = account_new(NULL, "myaccount"); acc->host = xstrdup("smtp.example.com"); acc->port = 587; acc->from = xstrdup("user@example.com"); ``` -------------------------------- ### smtp_tls_starttls() Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Sends the STARTTLS command to the server, used for servers supporting explicit TLS upgrade. After this, `smtp_tls()` should be called to complete the handshake, followed by `smtp_init()` to detect new capabilities. ```APIDOC ## smtp_tls_starttls() ### Description Send STARTTLS command to the server. Use this for servers supporting explicit TLS upgrade. ### Parameters #### Path Parameters - **srv** (smtp_server_t*) - Required - SMTP server after smtp_init() - **error_msg** (list_t**) - Required - Output: server response lines (list of strings) - **errstr** (char**) - Required - Output: error message on failure ### Returns - `SMTP_EOK` on success - `SMTP_EIO` — I/O error - `SMTP_EPROTO` — protocol violation - `SMTP_EINVAL` — invalid command ### Example ```c // For servers with STARTTLS support (port 587) if (smtp_init(&srv, "localhost", &msg, &errstr) == SMTP_EOK) { if (srv->cap.flags & SMTP_CAP_STARTTLS) { smtp_tls_starttls(&srv, &msg, &errstr); // then call smtp_tls() and smtp_init() again } } ``` ``` -------------------------------- ### Initialize SMTP Session Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Initializes the SMTP session by sending the EHLO/HELO command. This function must be called after connection and after starting TLS. It populates server capabilities. ```c int smtp_init(smtp_server_t *srv, const char *ehlo_domain, list_t **msg, char **errstr); ``` ```c list_t *msg = NULL; char *errstr = NULL; if (smtp_init(&srv, "localhost", &msg, &errstr) == SMTP_EOK) { printf("Server caps: size=%ld flags=0x%x\n", srv->cap.size, srv->cap.flags); list_free(msg); } ``` -------------------------------- ### Initialize Networking Library Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/networking.md Call net_lib_init() before any other networking functions. It requires a pointer to a char** for error messages. ```c char *errstr = NULL; if (net_lib_init(&errstr) != NET_EOK) { fprintf(stderr, "Network init failed: %s\n", errstr); free(errstr); return 1; } ``` -------------------------------- ### Send ETRN Request Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Send a Remote Message Queue Starting (ETRN) request to the server as defined in RFC 1985. The etrn_argument specifies the hostname for which to request queue flushing. ```c int smtp_etrn(smtp_server_t *srv, const char *etrn_argument, list_t **msg, char **errstr); ``` -------------------------------- ### base64_decode_ctx_init() Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Initializes a context structure for stateful Base64 decoding. ```APIDOC ## base64_decode_ctx_init() ### Description Initializes a `base64_decode_context` structure `ctx` for stateful Base64 decoding. ### Signature ```c void base64_decode_ctx_init(struct base64_decode_context *ctx); ``` ``` -------------------------------- ### Handle SMTP Error Codes Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md Provides an example of checking the return code from an SMTP operation and handling specific errors like authentication failure or insecurity, along with a general fallback for other errors. ```c if (ret != SMTP_EOK) { if (ret == SMTP_EAUTHFAIL) { // handle auth error } else if (ret == SMTP_EINSECURE) { // handle insecurity } else { // handle other errors } } ``` -------------------------------- ### net_lib_init() Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/networking.md Initializes the networking library. This function must be called before any other networking functions are used. It can output an error message if initialization fails. ```APIDOC ## net_lib_init() ### Description Initializes the networking library. Must be called before any other net_* functions. ### Parameters #### Path Parameters - **errstr** (char**) - Required - Output: error message on failure ### Returns - `NET_EOK` on success - `NET_ELIBFAILED` — initialization failed (errstr will be set) ### Request Example ```c char *errstr = NULL; if (net_lib_init(&errstr) != NET_EOK) { fprintf(stderr, "Network init failed: %s\n", errstr); free(errstr); return 1; } ``` ``` -------------------------------- ### Initialize MD5 Context Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Initializes an MD5_CTX structure to prepare it for a new MD5 hash computation. ```c void MD5_Init(MD5_CTX *ctx); ``` -------------------------------- ### Handle SMTP_EUNAVAIL Unavailable Service Error Source: https://github.com/marlam/msmtp/blob/master/_autodocs/errors.md This example demonstrates handling unavailable service errors (SMTP_EUNAVAIL), often resulting from server-side rejections. It checks the SMTP status code to determine if a retry is appropriate. ```c list_t *error_msg = NULL; char *errstr = NULL; int ret = smtp_end_mail(&srv, &error_msg, &errstr); if (ret == SMTP_EUNAVAIL) { // Check status code to decide if retry is possible int status = smtp_msg_status(error_msg); if (status >= 500) { fprintf(stderr, "Permanent error: server rejected mail\n"); // Don't retry } else { fprintf(stderr, "Temporary error: %d\n", status); // Can retry later } list_free(error_msg); } free(errstr); ``` -------------------------------- ### Handle Insecure Configuration File Permissions (CONF_EINSECURE) Source: https://github.com/marlam/msmtp/blob/master/_autodocs/errors.md This snippet illustrates how to handle insecure file permissions for a configuration file. It checks for the `CONF_EINSECURE` error code and provides a specific `chmod` command to fix the permissions, recommending `0600` for security. ```c if (ret == CONF_EINSECURE) { fprintf(stderr, "Config file insecure: %s\n", errstr); fprintf(stderr, "Fix with: chmod 0600 ~/.msmtprc\n"); } ``` -------------------------------- ### Validate Account Configuration Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md Shows how to validate an account configuration before using it, checking for errors and printing a message if the configuration is invalid. ```c if ((ret = check_account(acc, 0, &errstr)) != CONF_EOK) { fprintf(stderr, "Invalid account: %s\n", errstr); free(errstr); return 1; } ``` -------------------------------- ### Detect Circular Alias Definition Source: https://github.com/marlam/msmtp/blob/master/_autodocs/errors.md This example shows the structure of a circular alias definition, which would trigger an ALIASES_ELOOP error. It illustrates a scenario where alias 'a' points to 'b', 'b' points to 'c', and 'c' points back to 'a'. ```plaintext a: b b: c c: a ``` -------------------------------- ### MD5_Init(), MD5_Update(), MD5_Final() Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Provides functions for MD5 hashing. MD5_Init initializes the context, MD5_Update adds data to the hash, and MD5_Final finalizes the hash computation and outputs the 16-byte digest. ```APIDOC ## MD5 Hashing Functions ### Description Functions for MD5 hashing and HMAC. ### Functions #### MD5_Init() Initialize MD5 context. #### MD5_Update() Add data to MD5 hash. #### MD5_Final() Finalize and output 16-byte MD5 digest. ### Parameters #### MD5_Init() - **ctx** (MD5_CTX*) - Pointer to MD5 context structure #### MD5_Update() - **ctx** (MD5_CTX*) - Pointer to MD5 context structure - **data** (const void*) - Pointer to the data to be hashed - **size** (unsigned long) - Size of the data in bytes #### MD5_Final() - **result** (unsigned char*) - Buffer to store the 16-byte MD5 digest - **ctx** (MD5_CTX*) - Pointer to MD5 context structure ### Request Example ```c MD5_CTX ctx; unsigned char result[16]; const char *message = "Hello, world!"; MD5_Init(&ctx); MD5_Update(&ctx, message, strlen(message)); MD5_Final(result, &ctx); // result now contains the MD5 hash ``` ### Response #### Success Response (200) - `MD5_Init`: void - `MD5_Update`: void - `MD5_Final`: void (result buffer is populated) #### Response Example None provided. ``` -------------------------------- ### Initialize TLS Library Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/tls.md Initializes the TLS library. This function must be called before creating any TLS connections. It returns an error code and an error string if initialization fails. ```c char *errstr = NULL; if (mtls_lib_init(&errstr) != TLS_EOK) { fprintf(stderr, "TLS init failed: %s\n", errstr); free(errstr); return 1; } ``` -------------------------------- ### List Operations with Memory Management Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md Shows how to create a list of strings, insert elements, and then free both the list and its string contents using custom allocation functions. ```c #include "list.h" #include "xalloc.h" // Create list with strings list_t *recipients = list_new(); list_insert(list_last(recipients), xstrdup("alice@example.com")); list_insert(list_last(recipients), xstrdup("bob@example.com")); // ... use recipients ... // Clean up (free both list and strings) list_xfree(recipients, free); ``` -------------------------------- ### Execute Command and Capture Output Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Executes a given command string and captures its standard output into a buffer. Also captures any error messages. ```c int eval(const char *arg, char **buf, char **errstr); ``` -------------------------------- ### Create a New List Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/utilities.md Initializes an empty doubly-linked list. Returns a pointer to the head element. ```c list_t *head = list_new(); ``` -------------------------------- ### Connect to SMTP Server Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/smtp.md Establishes a TCP connection to an SMTP server. Use this to initiate communication with the mail server. ```c int smtp_connect(smtp_server_t *srv, const char *socketname, const char *proxy_host, int proxy_port, const char *host, int port, const char *source_ip, int timeout, char **server_canonical_name, char **server_address, char **errstr); ``` ```c smtp_server_t srv = smtp_new(NULL, SMTP_PROTO_SMTP); char *errstr = NULL; int ret = smtp_connect(&srv, NULL, NULL, 0, "smtp.example.com", 587, NULL, 30, NULL, NULL, &errstr); if (ret != NET_EOK) { fprintf(stderr, "Connection failed: %s\n", errstr); free(errstr); } ``` -------------------------------- ### Password Storage with passwordeval Source: https://github.com/marlam/msmtp/blob/master/_autodocs/configuration.md Demonstrates secure password storage options using 'passwordeval' with GPG, a password manager ('pass show'), or decryption of an encrypted file. ```msmtp passwordeval gpg -d ~/.msmtp-password.gpg passwordeval pass show account passwordeval cat ~/.msmtp-password-encrypted | decrypt ``` -------------------------------- ### Use xalloc Functions for Memory Allocation Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md Highlights the use of `xalloc` functions (like `xstrdup`) for memory allocation, emphasizing that these functions exit on out-of-memory conditions rather than returning NULL. ```c // xmalloc, xcalloc, xstrdup, etc. // Never return NULL, exit on OOM char *str = xstrdup("hello"); ``` -------------------------------- ### Send Mail Using Configuration Account Source: https://github.com/marlam/msmtp/blob/master/_autodocs/api-reference/integration.md This function demonstrates how to send an email using account settings defined in an msmtp configuration file. It handles parsing the configuration, finding the specified account, establishing a connection, authenticating, and sending the email. ```c #include "conf.h" int send_mail_from_config(const char *account_name, const char *to, FILE *mail_data) { account_t *acc = NULL; list_t *accounts = NULL; char *errstr = NULL; int ret; // 1. Parse configuration file if ((ret = get_conf("~/.msmtprc", 1, &accounts, &errstr)) != CONF_EOK) { fprintf(stderr, "Config error: %s\n", errstr); free(errstr); return 1; } // 2. Find account acc = find_account(accounts, account_name); if (!acc) { fprintf(stderr, "Account '%s' not found\n", account_name); list_xfree(accounts, account_free); return 1; } // 3. Validate account if ((ret = check_account(acc, 0, &errstr)) != CONF_EOK) { fprintf(stderr, "Account error: %s\n", errstr); free(errstr); list_xfree(accounts, account_free); return 1; } // 4. Initialize networking and SMTP if (net_lib_init(&errstr) != NET_EOK) { fprintf(stderr, "net_lib_init: %s\n", errstr); free(errstr); list_xfree(accounts, account_free); return 1; } smtp_server_t srv = smtp_new(NULL, acc->protocol); // 5. Connect using account settings if ((ret = smtp_connect(&srv, acc->socketname, acc->proxy_host, acc->proxy_port, acc->host, acc->port, acc->source_ip, acc->timeout, NULL, NULL, &errstr)) != NET_EOK) { fprintf(stderr, "Connection failed: %s\n", errstr); free(errstr); smtp_close(&srv); net_lib_deinit(); list_xfree(accounts, account_free); return 1; } // 6. Initialize and optionally authenticate list_t *msg = NULL; smtp_get_greeting(&srv, &msg, NULL, &errstr); list_free(msg); smtp_init(&srv, acc->domain, &msg, &errstr); list_free(msg); if (acc->auth_mech && strcmp(acc->auth_mech, "off") != 0) { char *password = acc->password; if (!password && acc->passwordeval) { // Evaluate password command if (eval(acc->passwordeval, &password, &errstr) != 0) { fprintf(stderr, "passwordeval failed: %s\n", errstr); free(errstr); // error handling... } } if ((ret = smtp_auth(&srv, acc->host, acc->port, acc->username, password, acc->ntlmdomain, acc->auth_mech, NULL, &msg, &errstr)) != SMTP_EOK) { fprintf(stderr, "Authentication failed: %s\n", errstr); free(errstr); list_free(msg); // error handling... } list_free(msg); if (password != acc->password) free(password); } // 7. Send mail using account from address list_t *recipients = list_new(); list_insert(list_last(recipients), (void *)to); long size = 0; if ((ret = smtp_send_envelope(&srv, acc->from, recipients, acc->dsn_notify, acc->dsn_return, &msg, &errstr)) != SMTP_EOK) { fprintf(stderr, "send_envelope failed: %s\n", errstr); free(errstr); list_free(msg); list_free(recipients); // error handling... } list_free(msg); smtp_send_mail(&srv, mail_data, 1, 1, 1, 0, &size, &errstr); list_t *end_msg = NULL; smtp_end_mail(&srv, &end_msg, &errstr); list_free(end_msg); list_free(recipients); // 8. Cleanup smtp_quit(&srv, NULL); smtp_close(&srv); net_lib_deinit(); list_xfree(accounts, account_free); return 0; } ``` -------------------------------- ### Store Password in System Keyring Source: https://github.com/marlam/msmtp/blob/master/_autodocs/configuration.md Shows how to store credentials in the system keyring using 'secret-tool'. msmtp can automatically retrieve passwords from the keyring if not found in the configuration. ```bash secret-tool store --label=msmtp host smtp.example.com user myuser ```