SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor

VPS-এ mailcow: Gmail-এ গ্রহণযোগ্য email server তৈরি

mailcow ইনস্টলের আগে outbound port 25 ব্লক কি না পরীক্ষা করুন। না হলে mail queue-তে আটকে bounce হবে, আর ভুল DNS-এ Gmail দেখাবে 550 5.7.25 PTR rejection।

আপনি যা তৈরি করছেন

আপনার নিজস্ব সার্ভারে একটি সম্পূর্ণ mail server: মেসেজ পাঠানো ও গ্রহণের জন্য SMTP, ফোন ও laptop-এর মধ্যে mail sync রাখার জন্য IMAP, একটি webmail client এবং উভয় দিকের প্রতিটি মেসেজের score নির্ধারণকারী spam filter। mailcow-dockerized Postfix, Dovecot, Rspamd, SOGo webmail, MariaDB, Redis এবং একটি ACME client-কে এক Docker Compose stack-এ একত্র করে। তাই software-টি মূল সমস্যা নয়। আধা ঘণ্টার মধ্যে এটি চালু করতে পারবেন।

মূল সমস্যা হলো এর চারপাশের বিষয়গুলো। Email এমন একটি service, যেখানে Internet-এর বাকি অংশ নতুন server-কে সক্রিয়ভাবে অবিশ্বাস করে। “এটি কাজ করছে” এবং “Gmail নীরবে প্রতিটি message গ্রহণ করছে না”—এই দুই অবস্থার পার্থক্য মূলত 4টি DNS record এবং একটি IP-reputation setting-এর ওপর নির্ভর করে, যেটির ওপর আপনার সম্পূর্ণ নিয়ন্ত্রণ নাও থাকতে পারে। কোনো কিছু rent করার আগে নিচের prerequisites পড়ুন। এগুলো পড়ার পরে যদি reputation তৈরির দীর্ঘ প্রক্রিয়াটি আপনার কাছে মূল্যবান মনে না হয়, সেটিও একটি গ্রহণযোগ্য সিদ্ধান্ত। 2026 সালে বাস্তবে কোন বিষয়গুলো self-hosting করার মতো এই কারণেই email-কে “শুধু আপনি সত্যিই চাইলে” বিভাগে রেখেছে।

পূর্বশর্তগুলোই প্রকল্প

এগুলোর যেকোনো একটি বাদ পড়লে এমন মেইল পাঠাবেন, যা কখনো পৌঁছাবে না। মানুষকে সমস্যায় ফেলার দিক থেকে মোটামুটি বেশি ঘটার ক্রমে:

Outbound port 25 খোলা থাকতে হবে। আপনার সার্ভার TCP port 25 ব্যবহার করে Gmail এবং Microsoft-এর mail server-এ মেইল deliver করে। Spam ঠেকাতে VPS ও cloud provider-গুলোর বড় একটি অংশ ডিফল্টভাবে outbound 25 block করে। এই block নীরবে কার্যকর থাকে; boot-এর সময় কোনো error দেখা যায় না, সবকিছু সুস্থ মনে হয়, এবং Postfix হাল ছেড়ে মেইল bounce করা পর্যন্ত মেইল queue-তে deferred অবস্থায় পড়ে থাকে। mailcow সর্বোচ্চ queue lifetime পাঁচ দিন নির্ধারণ করে। কিছু install করার আগে এটি পরীক্ষা করুন। এটি block থাকলে একমাত্র সমাধান হলো provider-কে support ticket পাঠিয়ে port খুলে দিতে বলা। কিছু provider পুরোনো account-এর জন্য এটি খুলে দেয়, আবার কিছু provider কখনোই খুলবে না।

ব্যবহারযোগ্য reputation-সহ পরিষ্কার IP। Recycled VPS IP আগের tenant-এর spam-এর কারণে প্রায়ই আগে থেকেই blocklist-এ থাকে। সিদ্ধান্ত নেওয়ার আগে Spamhaus lookup বা mxtoolbox-এর মতো service-এ আপনার IP পরীক্ষা করুন। তালিকাভুক্ত IP হলে এমন rejection হবে, যা code দিয়ে সমাধান করা যায় না।

DNS-এর নিয়ন্ত্রণ এবং সঠিক PTR record। আপনার domain-এর zone-এ record যোগ করার ক্ষমতা দরকার। একই সঙ্গে server-এর IP-এর জন্য reverse DNS (PTR) দরকার, যা আপনার mail hostname-এ নির্দেশ করবে। PTR প্রায় কখনোই আপনার DNS panel-এ set করা হয় না। এটি IP-এর মালিকের নিয়ন্ত্রণে থাকে। তাই এটি VPS provider-এর control panel অথবা support ticket-এর মাধ্যমে set করতে হয়।

6 GiB RAM এবং 2 vCPU হলো স্বাচ্ছন্দ্যে চালানোর ন্যূনতম ভিত্তি। Private install-এর জন্য mailcow-এর নিজস্ব minimum হলো 6 GiB RAM এবং অতিরিক্ত 1 GiB swap। কয়েকজন user নিয়মিত ব্যবহার শুরু করলে 8 GiB RAM নেওয়ার পরামর্শ দেওয়া হয়। প্রায় 2.5 GiB-এর নিচে গেলে, kernel যাতে container বন্ধ করে দিতে শুরু না করে, সে জন্য generate_config.sh ClamAV virus scanner disable করার প্রস্তাব দেয়। কোনো মেইল store করার আগেই mailcow-এর নথিভুক্ত disk minimum 20 GiB। তাই শুরুতেই এর চেয়ে বেশি disk দিন এবং mailbox বড় হওয়ার জন্য অতিরিক্ত স্থান রাখুন।

Bare IP নয়, একটি DNS name। mail.example.com-এর মতো একটি hostname বেছে নিন। এই একক name-ই আপনার MAILCOW_HOSTNAME, TLS certificate subject, PTR target এবং SMTP banner হবে। সব জায়গায় একই name ব্যবহার করুন।

ধাপ 1, outbound port 25 খোলা আছে কি না প্রমাণ করুন

এটি প্রথমে করুন। এটি ব্যর্থ হলে বাকি সব প্রচেষ্টা বৃথা। নতুন VPS থেকে একটি প্রকৃত mail server-এর সঙ্গে SMTP conversation শুরু করার চেষ্টা করুন:

sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 gmail-smtp-in.l.google.com 25

সফল ফলাফল সঙ্গে সঙ্গেই দেখা যাবে:

Connection to gmail-smtp-in.l.google.com (142.250.x.x) 25 port [tcp/smtp] succeeded!

port block করা থাকলে পুরো পাঁচ সেকেন্ড অপেক্ষা করে, তারপর ব্যর্থ হবে:

nc: connect to gmail-smtp-in.l.google.com port 25 (tcp) timed out: Operation now in progress

নিজস্ব outbound firewall rule না থাকা নতুন VPS-এ এই timeout provider-এর block নির্দেশ করে। এটি provider-এর দিকের network filter, আপনার firewall নয়। তাই কোনো local পরিবর্তনে এটি ঠিক হবে না। একটি ticket খুলে লিখুন: "<IP>-এর জন্য আমার VPS-এ outbound TCP port 25 enable করুন; আমি একটি বৈধ mail server চালাচ্ছি।" এটি "succeeded" না দেখানো পর্যন্ত mailcow install করবেন না। মনে রাখবেন, inbound 25 অর্থাৎ অন্য server আপনার server-এ পৌঁছানো, একটি আলাদা path এবং এটি সাধারণত খোলা থাকে। Provider-রা সাধারণত outbound দিকটিই throttle করে।

ধাপ 2, এখন DNS record সেট করুন

DNS পরিবর্তন কার্যকর হতে সময় লাগে। তাই installation শুরু করার আগে যতটা সম্ভব সবকিছু publish করুন। ধরে নিন, আপনার domain হলো example.com, mail host হলো mail.example.com, এবং IP হলো 10.0.0.10। আপনার zone-এ তৈরি করুন:

mail.example.com.        A      10.0.0.10
mail.example.com.        AAAA   2001:db8::10          ; only if you have IPv6
example.com.             MX  10 mail.example.com.
example.com.             TXT    "v=spf1 mx -all"
_dmarc.example.com.      TXT    "v=DMARC1; p=none; rua=mailto:postmaster@example.com"

SPF record-এর অর্থ হলো: “শুধু আমার MX এই domain-এর হয়ে mail পাঠাতে পারবে; বাকিগুলো প্রত্যাখ্যান করুন।” নিজের mail reject না করে report পর্যবেক্ষণ করতে DMARC শুরু করুন p=none দিয়ে। Alignment যাচাই হয়ে গেলে এটি প্রথমে p=quarantine এবং পরে p=reject-এ কঠোর করুন। দুটি record ইচ্ছাকৃতভাবে এখনো অনুপস্থিত: DKIM, যা Step 6-এ mailcow আপনার জন্য তৈরি করবে, এবং PTR, যা এখন আপনার provider-এর panel-এ সেট করতে হবে।

10.0.0.10-এর জন্য PTR (reverse DNS) mail.example.com-এ সেট করুন; এর exact value হলো MAILCOW_HOSTNAME। অধিকাংশ মানুষ এই একক record-টি ভুলে যান, কিন্তু বড় provider-গুলো এটি না থাকলে mail প্রত্যাখ্যান করে। আপনার panel-এ rDNS field না থাকলে একটি ticket খুলুন।

ধাপ 3, Docker ইনস্টল করুন

mailcow-এর জন্য Docker Engine 24.0 বা পরবর্তী সংস্করণ এবং Docker Compose 2.0 বা পরবর্তী সংস্করণ প্রয়োজন। Compose plugin (docker compose) ব্যবহার করাই সবচেয়ে সহজ পদ্ধতি। তবে mailcow standalone docker-compose binary-ও সমর্থন করে। Ubuntu-এর docker.io package ব্যবহার না করে Docker-এর official convenience script ব্যবহার করুন। ওই package-এ কোনো Compose plugin নেই:

curl -fsSL https://get.docker.com | sudo sh
sudo docker compose version

আপনার Docker Compose version line-এ v2.x বা v5.x দেখানোর কথা। 2025 সালে প্রকাশিত Compose v5 কার্যগতভাবে v2-এর সমান। তাই যেকোনো একটি mailcow-এর জন্য যথেষ্ট। docker compose version চালালে যদি docker: 'compose' is not a docker command দেখায়, তাহলে Docker Engine ইনস্টল হয়েছে, কিন্তু Compose plugin ইনস্টল হয়নি। Docker-এর repository থেকে plugin ইনস্টল করুন, উপরের script আবার চালান, অথবা আমাদের Docker Compose-এর মৌলিক নির্দেশিকা অনুসরণ করুন। এতে Docker-এর নিজস্ব apt repository থেকে উভয়টি সেট আপ করা হয়।

ধাপ 4, mailcow ক্লোন করুন এবং কনফিগারেশন তৈরি করুন

cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
umask
sudo ./generate_config.sh

umask যে 0022 প্রিন্ট করে, তা যাচাই করা mailcow-এর নিজস্ব ইনস্টল ধাপের অংশ। এই ধাপগুলো ক্লোন করার আগে umask 0022 সেট করে। mailcow কোনোভাবেই এই মান পরীক্ষা করে না, এবং নতুন Ubuntu 24.04 root shell-এ আগে থেকেই 0022 পাওয়া যায়। এরপর স্ক্রিপ্টটি গুরুত্বপূর্ণ একটিমাত্র তথ্য জানতে চায়: fully qualified hostname। mail.example.com লিখুন। এই মানটি আপনার A record এবং PTR record-এর সঙ্গে হুবহু মিলতে হবে। স্ক্রিপ্টটি mailcow.conf লিখে তৈরি করে। পুরো stack এই একটিমাত্র environment file পড়ে। Web port পরিবর্তন করতে হলে (HTTP_PORT, HTTPS_PORT), অথবা ছোট মেশিনে ClamAV নিষ্ক্রিয় করতে হলে, এটি খুলুন:

MAILCOW_HOSTNAME=mail.example.com
HTTP_PORT=80
HTTPS_PORT=443
SKIP_CLAMD=n          # set to y to drop the virus scanner on a <2.5 GiB box

কম RAM-এর মেশিনে SKIP_FTS=y আরেকটি গুরুত্বপূর্ণ নিয়ন্ত্রণ। mailcow-এর documentation-এ full-text search-কে দ্বিতীয় বড় memory consumer বলা হয়েছে। এটি বাদ দিলে শুধু webmail-এ body-text search সুবিধাটি থাকবে না।

অন্য কোনো service আগে থেকেই এই port-গুলো ব্যবহার না করলে HTTP_PORT=80 এবং HTTPS_PORT=443 অপরিবর্তিত রাখুন। mailcow-এর built-in ACME client ডিফল্টভাবে HTTP-01 challenge ব্যবহার করে। Certificate পেতে port 80 Internet থেকে reachable থাকতে হয়। (mailcow 2026-03 এবং পরের সংস্করণগুলোতে ACME_DNS_CHALLENGE=y ব্যবহার করে DNS-01 challenge-ও নেওয়া যায়। এতে port 80 দরকার হয় না, তবে DNS host-এর API access দরকার হয়।) এই কারণে সাধারণ বিন্যাসে একই মেশিনে আলাদা nginx এবং Certbot সেটআপ চালানো হয় না। mailcow নিজেই অভ্যন্তরীণভাবে TLS certificate ইস্যু ও renew করে, এবং port 80/443 দখল করে রাখা দ্বিতীয় service এই প্রক্রিয়া ব্যাহত করে। mailcow বিকল্প পদ্ধতিটিও নথিভুক্ত করেছে: HTTP_BIND=127.0.0.1 HTTP_PORT=8080 HTTPS_BIND=127.0.0.1 HTTPS_PORT=8443 ব্যবহার করে এর web listener-গুলো স্থানীয়ভাবে bind করুন, port 80 ও 443-এ একটি reverse proxy রাখুন, এবং স্থানীয় Certbot-কে certificate পরিচালনা করাতে চাইলে mailcow-কে সেই certificate-গুলোর দিকে নির্দেশ করে renewal hook যোগ করুন। Mail server-এ এতে অতিরিক্ত কয়েকটি component পরিচালনা করতে হয়। তাই public web front end চায় এমন অন্য service-এর ক্ষেত্রেও একই সিদ্ধান্ত প্রযোজ্য: Halcyon দিয়ে Jellyfin library-কে 90s-এর video store হিসেবে নতুন করে সাজানো-র মতো build, যা port 443-এ নিজস্ব reverse proxy প্রত্যাশা করে, আলাদা host-এ রাখা উচিত—যদি না mailcow-কে সেই proxy-এর পেছনে স্থানান্তর করেন। ব্যতিক্রম হলো এমন service, যা কখনো public web port চায় না: একটি self-hosted RustDesk relay শুধু নিজের 21115 থেকে 21119 port range-এ listen করে। তাই পর্যাপ্ত bandwidth headroom থাকলে এটি একই মেশিনে চালানো যায়।

ধাপ 5, stack চালু করে লগ ইন করুন

sudo docker compose pull
sudo docker compose up -d
sudo docker compose ps

pull প্রক্রিয়ায় প্রায় দুই ডজন image fetch হয়; কয়েক মিনিট সময় দিন। docker compose ps-এ প্রতিটি container running (অথবা healthy) দেখালে browser-এ https://mail.example.com/admin খুলুন। ডিফল্ট admin login হলো username admin এবং password moohoo। System → Configuration, তারপর Access → Administrators-এ গিয়ে admin UI থেকে সঙ্গে সঙ্গে password পরিবর্তন করুন। browser যদি NET::ERR_CERT_AUTHORITY_INVALID সতর্কতা দেখায়, তাহলে এখনও ACME certificate issue হয়নি। এটি broken ধরে নেওয়ার আগে নিচের ACME failure অংশ দেখুন; প্রথম এক-দুই মিনিট self-signed placeholder থাকা স্বাভাবিক।

ধাপ 6, একটি ডোমেইন ও মেইলবক্স যোগ করুন এবং DKIM প্রকাশ করুন

অ্যাডমিন UI-তে E-Mail → Configuration খুলুন। Domains ট্যাবের অধীনে Add domain-এ ক্লিক করে example.com লিখুন। এরপর Mailboxes-এর অধীনে Add mailbox-এ ক্লিক করে একটি পাসওয়ার্ডসহ you@example.com তৈরি করুন। এটি ইতিমধ্যেই IMAP-এর মাধ্যমে ব্যবহারযোগ্য একটি কার্যকর মেইলবক্স।

এখন DKIM key তৈরি করুন। System → Configuration-এ যান। তারপর Options → ARC/DKIM keys খুলুন। ডোমেইন যোগ করার সময় mailcow ইতিমধ্যে একটি key তৈরি করে থাকতে পারে। না হলে সেখানে একটি key তৈরি করুন, ডোমেইন নির্বাচন করুন, selector হিসেবে dkim অপরিবর্তিত রাখুন, 2048-bit নির্বাচন করুন এবং Add-এ ক্লিক করুন। প্রদর্শিত দীর্ঘ TXT value কপি করে এভাবে প্রকাশ করুন:

dkim._domainkey.example.com.  TXT  "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqh...long-key...QAB"

mailcow-এর Domains পৃষ্ঠায় DNS button রয়েছে। এতে প্রত্যাশিত প্রতিটি record-এর তালিকা দেখা যায় এবং বাস্তবে প্রকাশিত record-এর পাশে green tick বা red cross দেখায়। এটিকে checklist হিসেবে ব্যবহার করুন। Deliverability পরীক্ষা করার আগে প্রতিটি row green করুন। প্রকাশ করার পর DKIM row red দেখালে সাধারণত key-টি TXT chunk-এ ভুলভাবে ভাগ করা হয়েছে। একটি 2048-bit key একক TXT string-এর 255-character সীমার চেয়ে দীর্ঘ। তাই এটিকে একটি logical value হিসেবে paste করুন এবং আপনার DNS host-কে এটি নিজে chunks-এ ভাগ করতে দিন।

ধাপ 7, মেইল deliverability পরীক্ষা করুন এবং 10/10 অর্জন করুন

mail-tester.com-এ যান। সেখানে দেখানো random address কপি করুন। আপনার নতুন mailbox থেকে ওই address-এ একটি message পাঠান। SOGo webmail-এ https://mail.example.com/SOGo ঠিকানায় log in করে সেখান থেকেও message পাঠান। এরপর "Then check your score" ক্লিক করুন।

10/10 অর্জনের লক্ষ্য রাখুন। সাধারণত নিচের কারণে score কমে:

  • SPF not aligned, আপনার MX/SPF record অনুপস্থিত, অথবা sending IP এতে অন্তর্ভুক্ত নয়। SPF TXT আবার পরীক্ষা করুন।
  • DKIM signature does not verify, dkim._domainkey TXT অনুপস্থিত, এখনও propagate হয়নি, অথবা বিকৃত হয়েছে। এটিই সবচেয়ে সাধারণ সমস্যা।
  • No PTR / PTR mismatch, reverse DNS mail.example.com-এ resolve হচ্ছে না। provider-এর কাছে এটি ঠিক করুন।
  • Listed on a blocklist, আপনার IP-এর আগের reputation-এর কারণে এটি blocklist-এ রয়েছে। delisting-এর অনুরোধ করুন অথবা cleaner IP চান।

এটি 10/10 না হওয়া পর্যন্ত Gmail বা Outlook-এ real mail পাঠাবেন না। নতুন IP-এর সঙ্গে low score থাকলে প্রথম দিনেই আপনার domain flag হওয়ার সম্ভাবনা থাকে।

ধাপ 8, একটি প্রকৃত mail client সংযুক্ত করুন

এই settings ব্যবহার করে Thunderbird, Apple Mail বা আপনার ফোনকে server-এর সঙ্গে সংযুক্ত করুন। সব client-এর জন্য server host হলো mail.example.com:

  • IMAP: port 993, SSL/TLS (অথবা STARTTLS সহ 143)
  • SMTP submission: port 465, SSL/TLS (অথবা STARTTLS সহ 587)
  • Username: সম্পূর্ণ address, you@example.com
  • Password: আপনি যে mailbox password সেট করেছেন

client-এর mail কখনো port 25 দিয়ে পাঠাবেন না। এই port শুধু server-to-server mail-এর জন্য। mailcow এখানে authenticated submission দেয় না, তাই এই port-এ নির্দেশ করা client-এর সংযোগ প্রত্যাখ্যান করা হয়। কোনো client যদি Relay access denied দেখায়, তাহলে সেটি port 25-এ অথবা authentication ছাড়া mail পাঠানোর চেষ্টা করছে। আপনার mailbox credentials ব্যবহার করে সেটিকে 465 অথবা 587 port-এ STARTTLS বা SSL/TLS সহ configure করুন।

ধাপ 9, যা সত্যিই গুরুত্বপূর্ণ তার ব্যাকআপ নিন

mailcow একটি backup script সরবরাহ করে, যা প্রতিটি stateful volume-এর snapshot তৈরি করে। এটি একটি external disk বা mounted remote-এ চালান:

sudo MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups \
  ./helper-scripts/backup_and_restore.sh backup all

all ছয়টি জিনিস সংরক্ষণ করে। এগুলোর যেকোনো একটি হারালে data হারাবে: vmail (প্রকৃত mailbox), crypt (vmail decrypt করার key; এটি ছাড়া key-টি অকার্যকর), mysql (domain, user, alias ও setting সংরক্ষণকারী MariaDB), redis (queue ও cache state), rspamd (শেখা spam/ham তথ্য), এবং postfix (mail queue)। এটি একটি helper container-এর ভিতরে চলে এবং compressed archive লেখে। তাই stack চালু থাকলেও backup consistent থাকে। এটি nightly cron job দিয়ে automated করুন এবং পুরোনো set মুছে ফেলতে --delete-days 14 যোগ করুন। কোনো cron job কাজ করা বন্ধ করলে তা নীরবে ব্যর্থ হয়। তাই script-এর exit status এমন কোনো মাধ্যমে পাঠান, যা আপনি সত্যিই লক্ষ্য করবেন; self-hosted ntfy server একই cron entry থেকে এক লাইনের curl request গ্রহণ করে এবং failure ঘটার রাতেই আপনার ফোনে notification পাঠায়। Restore করার জন্য একই script-এর সঙ্গে restore ব্যবহার করুন। এটি snapshot-এর তালিকা দেখায় এবং কোন data ফিরিয়ে আনবেন তা বেছে নেওয়ার সুযোগ দেয়। যে backup কখনো test-restore করা হয়নি, সেটি backup নয়, শুধু আশা। একটি scratch VPS-এ dry run করে দেখুন।

ধাপ 10, নির্ধারিত সময়সূচি অনুযায়ী আপডেট করুন

mailcow নিজস্ব script ব্যবহার করে আপডেট হয়। এই script নতুন code আনে, mailcow.conf migrate করে, image prefetch করে এবং ক্রমানুসারে container restart করে:

cd /opt/mailcow-dockerized
sudo ./update.sh --check   # reports whether an update exists, changes nothing
sudo ./update.sh           # applies it

প্রথমে backup নিন (ধাপ 9), কারণ schema migration আগের অবস্থায় ফিরিয়ে নেওয়া কঠিন। আপডেট নিয়মিত প্রকাশিত হয় এবং Internet-facing daemon-এর জন্য security fix অন্তর্ভুক্ত থাকে। তাই mail server-কে কয়েক মাস আপডেট না করে রাখবেন না। কোনো আপডেটের পরে কোনো container unhealthy থাকলে, sudo docker compose logs --tail=50 <service>-mailcow যে daemon আবার চালু হতে পারেনি তার নাম দেখায়।

হার্ডেনিং সম্পর্কে একটি নোট

mailcow নিজস্ব netfilter service (netfilter-mailcow) চালায়। এটি mail ও webmail port-এ অতিরিক্ত অনুরোধ পাঠানো IP-গুলো ban করে। তাই mail অংশটি ডিফল্টভাবেই সুরক্ষিত থাকে। তবে host-এর SSH এতে অন্তর্ভুক্ত নয়। SSH এখনও exposed থাকে এবং brute-force আক্রমণের শিকার হতে পারে। এই build-এর সঙ্গে SSH auth log monitor করা Fail2ban এবং key-only login ব্যবহার করুন। mailcow admin UI-তে শক্তিশালী password দিন। সম্ভব হলে এটিকে public internet-এর বাইরে রাখুন অথবা VPN-এর পেছনে রাখুন।

ব্যর্থতার ধরন, নির্দিষ্ট স্ট্রিংসহ

Mail queue-তে বার্তা জমে থাকে এবং কখনো delivered হয় না। sudo docker compose exec postfix-mailcow postqueue -p চালান, অথবা admin UI-এর mail queue দেখুন; entry-গুলো deferred অবস্থায় থাকে। Postfix সেগুলো bounce করার আগে সর্বোচ্চ পাঁচ দিন পর্যন্ত অপেক্ষা করে। লগে দেখা যেতে পারে:

status=deferred (connect to gmail-smtp-in.l.google.com[142.250.x.x]:25: Connection timed out)

এর কারণ প্রায় সব সময় provider-এর পক্ষ থেকে outbound port 25 block করা (Step 1)। নিজের host firewall-এর outbound rule থেকেও একই timeout হতে পারে, তাই প্রথমে সেটি বাদ দিন। host firewall পরিষ্কার থাকলে configuration পরিবর্তন করে এটি ঠিক করা যাবে না; provider-এর কাছে ticket খুলুন। এটি DNS বা TLS-এর সমস্যা নয়। Remote MX-এর সঙ্গে port 25-এ timed out শব্দটি দেখা যাওয়াই এর প্রধান লক্ষণ।

Gmail সব বার্তাকে spam হিসেবে চিহ্নিত করে অথবা bounce করে। Gmail-এ বার্তাটি খুলুন, "Show original" নির্বাচন করুন এবং authentication result দেখুন। dkim=fail বা dkim=none দেখালে আপনার dkim._domainkey TXT record অনুপস্থিত, ভুলভাবে পরিবর্তিত, অথবা এখনো propagate হয়নি। ARC/DKIM page-এ দেখানো মানটি হুবহু আবার publish করুন এবং TTL শেষ হওয়া পর্যন্ত অপেক্ষা করুন। spf=fail দেখালে SPF/MX record আপনার IP-কে অন্তর্ভুক্ত করে না। Alignment অত্যন্ত গুরুত্বপূর্ণ; একটি check ব্যর্থ হলেই বার্তা spam-এ যেতে পারে।

সংযোগের সময় বড় provider-গুলো বার্তা প্রত্যাখ্যান করে। Bounce message বা Postfix log-এ Gmail-এর PTR rejection দেখা যেতে পারে:

550-5.7.25 [10.0.0.10] The IP address sending this message does not have a PTR
550-5.7.25 record setup, or the corresponding forward DNS entry does not match
550 5.7.25 the sending IP. As a policy, Gmail does not accept messages from IPs
550 5.7.25 with missing PTR records.

550 5.7.25 code-এর অর্থ reverse DNS অনুপস্থিত বা মেলেনি। Provider-এর কাছে আপনার IP-এর PTR হিসেবে mail.example.com সেট করুন (Step 2)। Forward (A) এবং reverse (PTR) record-এ মিল থাকতে হবে, এবং mailcow অন্য server-কে যে host name জানায়, উভয় record-এ একই host-এর নাম থাকতে হবে।

Browser-এ এমন certificate warning দেখায় যা দূর হয় না। acme-mailcow container একটি valid certificate সংগ্রহ করতে ব্যর্থ হয়েছে। এর log দেখুন:

sudo docker compose logs acme-mailcow | tail -n 40

Cannot validate any hostnames, skipping Let's Encrypt for 1 hour.-এর মতো কোনো line অথবা challenge failure দেখালে বোঝায়, Internet থেকে port 80-এ পৌঁছানো যাচ্ছে না, অথবা A record এই server-কে নির্দেশ করছে না। AAAA record publish করে থাকলে সেটিও পরীক্ষা করুন। mailcow প্রথমে AAAA record অনুযায়ী validation করে এবং AAAA record থাকলে A record পরীক্ষা করে না। তাই ভুল AAAA record অথবা port 80-এ পৌঁছাতে না-পারা IPv6 path থাকলে সঠিক A record থাকা সত্ত্বেও validation ব্যর্থ হবে। mail.example.com এই server-এ resolve হচ্ছে কি না নিশ্চিত করুন, host firewall-এর মাধ্যমে 80 এবং 443 port খোলা আছে কি না দেখুন, এবং অন্য কোনো process ওই port-গুলোতে bind করছে কি না পরীক্ষা করুন। কারণ ঠিক করার পরে এক ঘণ্টার back-off শেষ হওয়ার জন্য অপেক্ষা না করে sudo docker compose restart acme-mailcow দিয়ে client restart করুন।

FAQ

Self-hosted email কি আসলেই সার্থক?

আপনি যদি data ownership, unlimited alias এবং পূর্ণ নিয়ন্ত্রণ চান, তাহলে হ্যাঁ—VPS-এর খরচে mailcow আপনাকে একটি পেশাদার stack দেয়। তবে deliverability বজায় রাখা নিয়মিত কাজ: IP reputation, DNS alignment এবং blocklist monitoring কখনো পুরোপুরি শেষ হয় না। কোনো গুরুত্বপূর্ণ business address-এর ক্ষেত্রে এক দিন কারও spam folder-এ চলে যাওয়াতেই যদি আপনার ক্ষতি হয়, তাহলে managed provider ব্যবহার করাই বাস্তবসম্মত সিদ্ধান্ত। সুবিধার চেয়ে নিয়ন্ত্রণকে বেশি গুরুত্ব দিলে এবং নিয়মিত রক্ষণাবেক্ষণ করতে প্রস্তুত থাকলে self-host করুন। আপনার প্রকৃত লক্ষ্য যদি email নয়, বরং অন্যের server থেকে নিজের data সরিয়ে রাখা হয়, তাহলে এমন একটি service দিয়ে শুরু করুন যার ওপর অন্য কারও সিদ্ধান্তের অধিকার নেই: photo library-তে deliverability সমস্যা নেই, এবং একই ধরনের VPS-এ সেই build-এর জন্য প্রয়োজনীয় RAM floor ও backup command সম্পর্কে আমাদের PhotoPrism এবং Immich তুলনা দেখুন।

outbound port 25 block করা হয়েছে কি না কীভাবে বুঝব?

server থেকে nc -vz -w 5 gmail-smtp-in.l.google.com 25 চালান। "succeeded!" দেখালে port খোলা আছে; বিরতির পরে timed out দেখা গেলে port block করা হয়েছে। নিজের কোনো outbound firewall rule না থাকলে এর জন্য আপনার provider দায়ী। Self-hosted server mail receive করতে পারলেও send করতে না পারার সবচেয়ে সাধারণ কারণ এটি। Provider block-এর একমাত্র সমাধান হলো provider-কে port খুলে দিতে বলা; কোনো local setting এটি পরিবর্তন করতে পারে না।

আমার mail এখনও Gmail-এর spam folder-এ যায় কেন?

প্রায় সব ক্ষেত্রেই authentication chain-এ সমস্যা থাকে। Gmail-এ "Show original" ব্যবহার করে spf=pass, dkim=pass এবং dmarc=pass খুঁজুন। dkim=fail দেখা গেলে কোনো dkim._domainkey TXT record অনুপস্থিত বা ভুলভাবে তৈরি হয়েছে। PTR mismatch অথবা sending history ছাড়া নতুন IP-ও deliverability ক্ষতিগ্রস্ত করে। প্রথমে mail-tester.com-এ 10/10 পাওয়ার চেষ্টা করুন। এরপর IP ধীরে ধীরে warm up করুন—প্রথমে দিনে কয়েকটি message পাঠিয়ে ধীরে ধীরে সংখ্যা বাড়ান, প্রথম দিনেই বিপুল volume পাঠাবেন না।

ঠিক কোন কোন জিনিসের backup নিতে হবে?

backup_and_restore.sh backup all চালান এবং পুরো set-টি server-এর বাইরে সংরক্ষণ করুন। এতে vmail (mailbox), crypt (mailbox decrypt করার key), MariaDB database (domain, user, alias এবং setting), Redis, Rspamd-এর learned data এবং Postfix queue সংরক্ষিত হয়। crypt volume-টি অনেকে বাদ দেন। এটি ছাড়া vmail backup unreadable ciphertext হয়ে থাকে। অন্তত একবার একটি অস্থায়ী scratch box-এ restore পরীক্ষা করুন।

2 GB VPS-এ কি mailcow চালানো যাবে?

স্বচ্ছন্দে নয়। প্রায় 2.5 GiB-এর কম memory থাকলে generate_config.sh ClamAV disable করার প্রস্তাব দেয়। ClamAV বন্ধ থাকলেও Rspamd, Dovecot, MariaDB এবং stack-এর অন্যান্য অংশ memory-এর জন্য প্রতিযোগিতা করে। ফলে বাস্তব load থাকলে swap ব্যবহার এবং OOM kill ঘটবে। স্থিতিশীল single-user install-এর জন্য 6 GiB memory এবং 1 GiB swap-কে সর্বনিম্ন ধরুন। দুজনের বেশি মানুষ নির্ভর করতে শুরু করলেই 8 GiB-এ upgrade করুন।