Configuring Postfix to send emails via Yandex Cloud Postbox
In this tutorial, you will learn how to send emails via Yandex Cloud Postbox using Postfix
To start sending emails:
- Get your cloud ready.
- Create a VM for Postfix.
- Install and configure Postfix.
- Send an email.
- Send a MIME email with an attachment.
If you no longer need the resources you created, delete them.
Get your cloud ready
Sign up for Yandex Cloud and create a billing account:
- Navigate to the management console
and log in to Yandex Cloud or create a new account. - On the Yandex Cloud Billing
page, make sure you have a billing account linked and it has theACTIVEorTRIAL_ACTIVEstatus. If you do not have a billing account, create one and link a cloud to it.
If you have an active billing account, you can navigate to the cloud page
Learn more about clouds and folders here.
Required paid resources
The infrastructure support costs include:
- Fee for a continuously running VM (see Yandex Compute Cloud pricing).
- Fee for using a public IP address (see Yandex Virtual Private Cloud pricing).
- Fee for using Yandex Cloud Postbox (see Yandex Cloud Postbox pricing).
- Fee for public DNS queries and DNS zones, if you are creating a resource record in Cloud DNS (see Cloud DNS pricing).
Set up resources
-
Create an address.
-
Pass a domain ownership check.
-
Create a service account in the folder as the address. If you create the service account and address in different folders, you will get an error when attempting to send an email.
-
Create a key for the service account:
- To send an email over SMTP with API key authentication, create an API key. When creating an API key, set the scope for
yc.postbox.send. Save the secret key you got in a secure location. You will not be able to view the secret key parameters again after you close the window. - To send an email using the AWS CLI or via SMTP with password authentication, create a static access key. Save the ID and secret key to a secure location. You will not be able to view the secret key parameters again after you close the window.
- To send an email over SMTP with API key authentication, create an API key. When creating an API key, set the scope for
Create a VM for Postfix
-
In the management console
, select the folder where you want to create your VM. -
In the list of services, select Compute Cloud.
-
In the left-hand panel, select
Virtual machines. -
Click Create virtual machine.
-
Select Advanced setup.
-
Under Boot disk image, select the Ubuntu 24.04 LTS image.
-
Under Location, select the availability zone where your VM will reside.
-
Under Disks and file storages, configure the boot disk:
- Type:
HDD - Size:
20 GB
- Type:
-
Under Computing resources, navigate to the Custom tab and configure the recommended mail server settings as follows:
- Platform:
Intel Ice Lake - vCPU:
2 - Guaranteed vCPU performance:
100% - RAM:
2 GB
- Platform:
-
Under Network settings:
-
In the Subnet field, enter a subnet in the new VM's availability zone or select a cloud network from the list.
-
The cloud network must have at least one subnet. If there is no subnet, create one by selecting Create subnet.
-
If you do not have a network, click Create network to create one:
- In the window that opens, specify the network name and select the folder to host the network.
- Click Create network.
-
-
In the Public IP address field, select
Autoto assign a random external IP address from the Yandex Cloud pool to the VM. Alternatively, select a static address from the list if you reserved one.
-
-
Under Access, select SSH key and specify the VM access credentials:
-
In the Login field, enter a name for the user you want to create on the VM, e.g.,
ubuntu.Alert
Do not use
rootor other reserved usernames. To perform operations requiring root privileges, use thesudocommand. -
In the SSH key field, select the SSH key saved in your organization user profile.
If there are no SSH keys in your profile or you want to add a new key:
-
Click Add key.
-
Enter a name for the SSH key.
-
Select one of the following:
-
Enter manually: Paste the contents of the public SSH key. You need to create an SSH key pair on your own. -
Load from file: Upload the public part of the SSH key. You need to create an SSH key pair on your own. -
Generate key: Automatically create an SSH key pair.When adding a new SSH key, an archive containing the key pair will be created and downloaded. In Linux or macOS-based operating systems, unpack the archive to the
/home/<user_name>/.sshdirectory. In Windows, unpack the archive to theC:\Users\<user_name>/.sshdirectory. You do not need additionally enter the public key in the management console.
-
-
Click Add.
The system will add the SSH key to your organization user profile. If the organization has disabled the ability for users to add SSH keys to their profiles, the added public SSH key will only be saved in the user profile inside the newly created resource.
-
-
-
Under General information, specify the VM name. Follow these naming requirements:
- It must be from 2 to 63 characters long.
- It can only contain lowercase Latin letters, numbers, and hyphens.
- It must start with a letter and cannot end with a hyphen.
Note
The VM name is used to generate an internal FQDN, which is set only once, when you create the VM. If the internal FQDN is important to you, make sure to choose an appropriate name for your VM.
-
Click Create VM.
If you do not have the Yandex Cloud CLI installed yet, install and initialize it.
By default, the CLI uses the folder specified when creating the profile. To change the default folder, use the yc config set folder-id <folder_ID> command. You can also set a different folder for any specific command using the --folder-name or --folder-id parameter.
-
See the description of the CLI command for creating a VM:
yc compute instance create --help -
Create a VM in the default folder:
yc compute instance create \ --name postfix-server \ --zone ru-central1-b \ --platform-id standard-v3 \ --cores 2 \ --core-fraction 100 \ --memory 2 \ --create-boot-disk image-family=ubuntu-2404-lts,image-folder-id=standard-images,size=20GB,type=network-hdd \ --network-interface subnet-name=<subnet_name>,nat-ip-version=ipv4 \ --ssh-key <path_to_SSH_key>Where:
-
--name: VM name. Follow these naming requirements:- It must be from 2 to 63 characters long.
- It can only contain lowercase Latin letters, numbers, and hyphens.
- It must start with a letter and cannot end with a hyphen.
Note
The VM name is used to generate an internal FQDN, which is set only once, when you create the VM. If the internal FQDN is important to you, make sure to choose an appropriate name for your VM.
-
--zone: Availability zone corresponding to the selected subnet. -
--platform-id: Platform. -
--cores: Number of vCPUs the VM has. -
--core-fraction: Guaranteed vCPU share in %. -
--memory: VM RAM size. -
--create-boot-disk: Boot disk properties:sizestands for size, andimage-id, for the ID of the image being used. -
--network-interface: VM network interface settings:subnet-name: Name of the selected subnet.nat-ip-version=ipv4: Public IP address. To create a VM without a public IP address, omit this parameter.
-
--ssh-key: Path to the file with the public SSH key part and the file name. You need to create an SSH key pair on your own.
Result:
id: epde5biu1a4e******** folder_id: b1g681qpemb4******** created_at: "2025-08-20T11:01:11Z" name: postfix-server zone_id: ru-central1-b platform_id: standard-v3 resources: memory: "2147483648" cores: "2" core_fraction: "100" status: RUNNING metadata_options: gce_http_endpoint: ENABLED aws_v1_http_endpoint: ENABLED gce_http_token: ENABLED aws_v1_http_token: DISABLED boot_disk: mode: READ_WRITE device_name: epd1akno91gv******** auto_delete: true disk_id: epd1akno91gv******** network_interfaces: - index: "0" mac_address: d0:0d:**:**:**:** subnet_id: e2lb1da2dd9v******** primary_v4_address: address: 10.129.**.** one_to_one_nat: address: 84.201.***.*** ip_version: IPV4 serial_port_settings: ssh_authorization: OS_LOGIN gpu_settings: {} fqdn: epde5biu1a4e********.auto.internal scheduling_policy: {} network_settings: type: STANDARD placement_policy: {} hardware_generation: legacy_features: pci_topology: PCI_TOPOLOGY_V1 -
Use the create REST API method for the Instance resource or the InstanceService/Create gRPC API call.
Install and configure Postfix
-
Connect to the VM over SSH:
ssh -i <path_to_private_SSH_key> <VM_user_name>@<VM_public_IP_address> -
Install Postfix and the required modules:
sudo apt update sudo apt install -y postfix libsasl2-modules -
Once installation is complete, the Postfix setup interface will open in the terminal:
- In the first step, select
Internet with smarthost, then use TAB to select OK and press Enter. - Select OK in all subsequent steps.
- Wait for the setup to complete.
- In the first step, select
-
Run the following command to configure Postfix:
sudo postconf -e \ "relayhost = postbox.cloud.yandex.net:587" \ "smtp_sasl_auth_enable = yes" \ "smtp_sasl_security_options = noanonymous" \ "smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd" \ "smtp_use_tls = yes" \ "smtp_tls_security_level = secure" \ "smtp_tls_note_starttls_offer = yes" -
Check if a fallback relay is set and disable it if so:
-
Open the
terraform.tfvarsfile and find the following line:-o smtp_fallback_relay= -
If you find this line, prepend it with
#to comment it out. -
Save the file.
-
-
Provide your SMTP credentials for Yandex Cloud Postbox:
-
Open or create the
/etc/postfix/sasl_passwdfile and add the following line to it:postbox.cloud.yandex.net:587 SMTP_USERNAME:SMTP_PASSWORD -
Get authenticated:
API keyStatic access keyIn the
/etc/postfix/sasl_passwdfile:- Replace
SMTP_USERNAMEwith the API key ID you got when setting up your resources. - Replace
SMTP_PASSWORDwith the secret part of the API key.
-
Create a file named
generate.pyand paste this code into it:#!/usr/bin/env python3 import hmac import hashlib import base64 import argparse import sys # These values are required to calculate the signature. Do not change them. DATE = "20230926" SERVICE = "postbox" MESSAGE = "SendRawEmail" REGION = "ru-central1" TERMINAL = "aws4_request" VERSION = 0x04 def sign(key, msg): return hmac.new(key, msg.encode("utf-8"), hashlib.sha256).digest() def calculate_key(secret_access_key): signature = sign(("AWS4" + secret_access_key).encode("utf-8"), DATE) signature = sign(signature, REGION) signature = sign(signature, SERVICE) signature = sign(signature, TERMINAL) signature = sign(signature, MESSAGE) signature_and_version = bytes([VERSION]) + signature smtp_password = base64.b64encode(signature_and_version) return smtp_password.decode("utf-8") def main(): if sys.version_info[0] < 3: raise Exception("Must be using Python 3") parser = argparse.ArgumentParser( description="Convert a Secret Access Key to an SMTP password." ) parser.add_argument("secret", help="The Secret Access Key to convert.") args = parser.parse_args() print(calculate_key(args.secret)) if __name__ == "__main__": main() -
Generate a password:
python3 generate.py <secret_key>Where
<secret_key>is the secret key of the service account's static access key you got when setting up your resources.Use Python 3 or higher.
-
In the
/etc/postfix/sasl_passwdfile:- Replace
SMTP_USERNAMEwith the static access key ID. - Replace
SMTP_PASSWORDwith the generated password.
- Replace
- Replace
-
Save the
/etc/postfix/sasl_passwdfile.
-
-
Create a hash table with the credentials:
sudo postmap hash:/etc/postfix/sasl_passwd -
Restrict access to the credential files (recommended):
sudo chown root:root /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db sudo chmod 0600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db -
Provide the root certificate to verify the TLS connection:
sudo postconf -e 'smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt' -
Restart Postfix to apply the settings:
sudo systemctl restart postfix
Send an email
In this example, you will send a plain text email without attachments.
-
Run this command:
sendmail -f <sender_address> <recipient_address>Warning
Here and in subsequent steps, the sender address must match the domain you verified ownership for when setting up your resources.
-
Paste the following text into the terminal and press Enter:
From: <sender_address> Subject: Test Yandex Cloud Postbox via Postfix This is a test message sent via Yandex Cloud Postbox (SMTP, Postfix). . -
Check the recipient's mailbox.
If no email arrived, review the Postfix log:
/var/log/mail.log.
Message sending details
-
Once you run the
sendmail -f ... <recipient_address>command, the terminal switches to interactive email input mode. -
Start with the headers, entering one per line.
From:andSubject:are the required minimum.- The
From:header must match the domain allowed in Yandex Cloud Postbox. - The
To:header is optional since the recipient is already set in the command; however, you can add it for clarity.
- The
-
Insert a blank line to clearly separate headers from the email body.
-
Enter the email text. You may use more than one line.
-
End input by typing a single dot on a separate line and pressing Enter. Do not use spaces in this line.
-
If successful,
sendmailcompletes silently. To get verbose debug output, use the-vkey:sendmail -v -f <sender_address> <recipient_address> -
To cancel input without sending, press
Ctrl+C. -
For multiple recipients, list their addresses in the command, separating each with a space:
sendmail -f <sender_address> <recipient_1_address> <recipient_2_address> -
Do not use non-ASCII characters in this example. If non-ASCII (UTF-8) is required, encode:
- Headers according to RFC 2047. Here is an example for the email subject:
Subject: =?UTF-8?B?BASE64_ENCODED_SUBJECT?=. - Message body via MIME with
charset=UTF-8andContent-Transfer-Encoding: quoted-printableorbase64.
- Headers according to RFC 2047. Here is an example for the email subject:
-
For addresses with international domains, use Punycode
(IDNA ). Here is an example:sendmail -f user@xn--d1acpjx3f.xn--p1ai recipient@xn--e1afmkfd.xn--p1ai From: <user@xn--d1acpjx3f.xn--p1ai>
Send a MIME email with an attachment
In this example, you will send an email with HTML content and attached example.txt.
-
Create a file named
mime-email.txtand paste this code into it:From: <sender_address> Subject: Test email via Yandex Cloud Postbox MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="BOUNDARY-OUTER" --BOUNDARY-OUTER Content-Type: multipart/alternative; boundary="BOUNDARY-INNER" --BOUNDARY-INNER Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable This is the plain text part sent via Yandex Cloud Postbox SMTP. --BOUNDARY-INNER Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <html> <body> <h1>Hello!</h1> <p>This is the HTML part sent via Yandex Cloud Postbox SMTP.</p> </body> </html> --BOUNDARY-INNER-- --BOUNDARY-OUTER Content-Type: application/octet-stream MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="example.txt" U2FtcGxlIGF0dGFjaG1lbnQgY29udGVudA== --BOUNDARY-OUTER--Where:
From:: Sender's email address.Subject:: Email subject.
-
Send the email:
sendmail -f <sender_address> <recipient_address> < mime-email.txt -
Check the recipient's mailbox.
If no email arrived, review the Postfix log:
/var/log/mail.log.
Delete the resources you created
To stop paying for the resources you created: