Yandex Cloud
Search
Contact UsGet started
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
  • All Services
  • System Status
    • Featured
    • Infrastructure & Network
    • Data Platform
    • Containers
    • Developer tools
    • Serverless
    • Security
    • Monitoring & Resources
    • AI for business
    • Business tools
  • All Solutions
    • By industry
    • By use case
    • Economics and Pricing
    • Security
    • Technical Support
    • Start testing with double trial credits
    • Cloud credits to scale your IT product
    • Gateway to Russia
    • Cloud for Startups
    • Center for Technologies and Society
    • Yandex Cloud Partner program
  • Pricing
  • Customer Stories
  • Documentation
  • Blog
© 2025 Direct Cursus Technology L.L.C.
Tutorials
    • All tutorials
    • URL shortener
    • Ingesting data into storage systems
    • Storing application runtime logs
    • Deploying a web application using the Java Servlet API
    • Developing a Slack bot
    • Developing a Telegram bot
    • Developing a Telegram bot with AI agent support
    • Developing a custom integration in API Gateway
    • Developing CRUD APIs for movie services
    • Building a CI/CD pipeline in GitLab
    • GitLab Runner execution in Serverless Containers
    • Configuring CI/CD between Cloud Functions and SourceCraft
    • Configuring CI/CD between Cloud Functions and GitHub
    • Working with an API gateway via WebSocket
    • Building an interactive serverless application using WebSocket
    • Automatically copying objects from one Object Storage bucket to another
    • Visualizing logs in Grafana using the Cloud Logging plugin
    • Canary release of Cloud Functions
    • Interactive debugging of Cloud Functions
    • Creating a Node.js function using TypeScript
    • Running a containerized app in Serverless Containers
    • Streaming Yandex Cloud Postbox events to Data Streams and analyzing them with DataLens
    • Using API Gateway to set up speech synthesis in SpeechKit
    • Connecting to YDB from a Cloud Functions function in Python
    • Connecting to a YDB database from a Cloud Functions function in Node.js
    • API Gateway protection with Smart Web Security
    • Deploying a web app with JWT authorization in API Gateway and authentication in Firebase
    • Automatic data upload to Yandex SpeechSense using Yandex Workflows
    • Configuring responses in Cloud Logging and Yandex Cloud Functions
    • Setting up Workflows integration with Tracker, YandexGPT, and Yandex Cloud Postbox
    • Developing functions in Functions Framework and deploying them to Yandex Serverless Containers
    • Creating a Yandex Cloud Postbox address and checking domain ownership with Terraform
    • Creating an AI agent with Yandex Cloud Functions
    • Configuring Postfix to send emails via Yandex Cloud Postbox

In this article:

  • Get your cloud ready
  • Required paid resources
  • Set up resources
  • Create a VM for Postfix
  • Install and configure Postfix
  • Send an email
  • Send a MIME email with an attachment
  • Delete the resources you created
  1. Serverless technologies
  2. Configuring Postfix to send emails via Yandex Cloud Postbox

Configuring Postfix to send emails via Yandex Cloud Postbox

Written by
Yandex Cloud
Improved by
Danila N.
Updated at September 19, 2025
  • Get your cloud ready
  • Required paid resources
    • Set up resources
  • Create a VM for Postfix
  • Install and configure Postfix
  • Send an email
  • Send a MIME email with an attachment
  • Delete the resources you created

In this tutorial, you will learn how to send emails via Yandex Cloud Postbox using Postfix on a Yandex Compute Cloud VM.

To start sending emails:

  1. Get your cloud ready.
  2. Create a VM for Postfix.
  3. Install and configure Postfix.
  4. Send an email.
  5. Send a MIME email with an attachment.

If you no longer need the resources you created, delete them.

Get your cloud readyGet your cloud ready

Sign up for Yandex Cloud and create a billing account:

  1. Navigate to the management console and log in to Yandex Cloud or create a new account.
  2. On the Yandex Cloud Billing page, make sure you have a billing account linked and it has the ACTIVE or TRIAL_ACTIVE status. 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 to create or select a folder for your infrastructure.

Learn more about clouds and folders here.

Required paid resourcesRequired 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 resourcesSet up resources

  1. Create an address.

  2. Pass a domain ownership check.

  3. 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.

  4. Assign the postbox.sender role to the service account.

  5. 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.

Create a VM for PostfixCreate a VM for Postfix

Management console
Yandex Cloud CLI
API
  1. In the management console, select the folder where you want to create your VM.

  2. In the list of services, select Compute Cloud.

  3. In the left-hand panel, select Virtual machines.

  4. Click Create virtual machine.

  5. Select Advanced setup.

  6. Under Boot disk image, select the Ubuntu 24.04 LTS image.

  7. Under Location, select the availability zone where your VM will reside.

  8. Under Disks and file storages, configure the boot disk:

    • Type: HDD
    • Size: 20 GB
  9. 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
  10. 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 Auto to 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.

  11. 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 root or other reserved usernames. To perform operations requiring root privileges, use the sudo command.

    • 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:

      1. Click Add key.

      2. Enter a name for the SSH key.

      3. 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>/.ssh directory. In Windows, unpack the archive to the C:\Users\<user_name>/.ssh directory. You do not need additionally enter the public key in the management console.

      4. 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.

  12. 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.

  13. 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.

  1. See the description of the CLI command for creating a VM:

    yc compute instance create --help
    
  2. 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: size stands for size, and image-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 PostfixInstall and configure Postfix

  1. Connect to the VM over SSH:

    ssh -i <path_to_private_SSH_key> <VM_user_name>@<VM_public_IP_address>
    
  2. Install Postfix and the required modules:

    sudo apt update
    sudo apt install -y postfix libsasl2-modules
    
  3. Once installation is complete, the Postfix setup interface will open in the terminal:

    1. In the first step, select Internet with smarthost, then use TAB to select OK and press Enter.
    2. Select OK in all subsequent steps.
    3. Wait for the setup to complete.
  4. 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"
    
  5. Check if a fallback relay is set and disable it if so:

    1. Open the terraform.tfvars file and find the following line:

      -o smtp_fallback_relay=
      
    2. If you find this line, prepend it with # to comment it out.

    3. Save the file.

  6. Provide your SMTP credentials for Yandex Cloud Postbox:

    1. Open or create the /etc/postfix/sasl_passwd file and add the following line to it:

      postbox.cloud.yandex.net:587 SMTP_USERNAME:SMTP_PASSWORD
      
    2. Get authenticated:

      API key
      Static access key

      In the /etc/postfix/sasl_passwd file:

      • Replace SMTP_USERNAME with the API key ID you got when setting up your resources.
      • Replace SMTP_PASSWORD with the secret part of the API key.
      1. Create a file named generate.py and 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()
        
      2. 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.

      3. In the /etc/postfix/sasl_passwd file:

        • Replace SMTP_USERNAME with the static access key ID.
        • Replace SMTP_PASSWORD with the generated password.
    3. Save the /etc/postfix/sasl_passwd file.

  7. Create a hash table with the credentials:

    sudo postmap hash:/etc/postfix/sasl_passwd
    
  8. 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
    
  9. Provide the root certificate to verify the TLS connection:

    sudo postconf -e 'smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt'
    
  10. Restart Postfix to apply the settings:

    sudo systemctl restart postfix
    

Send an emailSend an email

In this example, you will send a plain text email without attachments.

  1. 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.

  2. 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).
    .
    
  3. 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: and Subject: 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.
  • 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, sendmail completes silently. To get verbose debug output, use the -v key:

    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-8 and Content-Transfer-Encoding: quoted-printable or base64.
  • 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 attachmentSend a MIME email with an attachment

In this example, you will send an email with HTML content and attached example.txt.

  1. Create a file named mime-email.txt and 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.
  2. Send the email:

    sendmail -f <sender_address> <recipient_address> < mime-email.txt
    
  3. Check the recipient's mailbox.

    If no email arrived, review the Postfix log: /var/log/mail.log.

Delete the resources you createdDelete the resources you created

To stop paying for the resources you created:

  1. Delete postfix-server.
  2. Delete the address.
  3. Delete the DNS zone if you created a resource record in it.

Was the article helpful?

Previous
Creating an AI agent with Yandex Cloud Functions
Next
All tutorials
© 2025 Direct Cursus Technology L.L.C.