Postfixでgmail宛の制限
gmail宛に1秒間隔、同時接続数3を実現したい。
smtp-destination_concurrency_limit
smtp-destination_rate_delay
は同時に設定できない(同時に設定しても同時接続数1になる)ので、
無理矢理実現。
以下は頑張って読もう
https://www.postfix-jp.info/trans-2.1/jhtml/access.5.html
mkdir -p /etc/postfix/userprogram/bin/
mkdir -p /etc/postfix/userprogram/def/
mkdir -p /etc/postfix/userprogram/log/
chown -R nobody:nobody /etc/postfix/userprogram/
/etc/postfix/userprogram/bin/check_policy_service.py
import sys
import logging
import socket
import os
import re
import yaml
from pathlib import Path
import random
# テスト用
import io
if len(sys.argv) > 1:
sys.stdin = io.StringIO(sys.argv[1])
#===============================================================================
# ロギング設定
#===============================================================================
def setup_logging():
host_name = socket.gethostname()
program_name = os.path.basename(__file__)
log_name = Path(__file__).stem + '.log'
log_file_path = Path(__file__).resolve().parent.parent / 'log' / log_name
logger = logging.getLogger()
logger.setLevel(logging.INFO)
file_handler = logging.FileHandler(log_file_path, encoding='utf-8')
file_handler.setFormatter(logging.Formatter(f'%(asctime)s {host_name} [{program_name}:%(levelname)s] [%(process)d] %(message)s', datefmt='%Y-%m-%d %H:%M:%S'))
stream_handler = logging.StreamHandler(sys.stdout)
stream_handler.setFormatter(logging.Formatter(f'%(asctime)s {host_name} [{program_name}:%(levelname)s] [%(process)d] %(message)s', datefmt='%Y-%m-%d %H:%M:%S'))
logger.addHandler(file_handler)
logger.addHandler(stream_handler)
#===============================================================================
# ユーティリティ関数
#===============================================================================
def load_transport_config(config_path):
"""
設定ファイルの読み込み。YAML構造が変更されたため、適応。
"""
with open(config_path, 'r') as file:
config = yaml.safe_load(file) # YAMLファイルの読み込み
services_config = config['check_policy_services'] # 新しいトップレベルキーに対応
compiled_services = []
for service_item in services_config:
for service_name, settings in service_item.items():
compiled_domains = [re.compile(domain) for domain in settings['domains']]
compiled_services.append({
'name': service_name,
'domains': compiled_domains,
'range': settings['range']
})
return compiled_services
def match_domain(transport_config, recipient_domain):
"""
ドメインの一致を判定する。
"""
for service in transport_config:
for domain_pattern in service['domains']:
if domain_pattern.match(recipient_domain):
return service['name'], service['range']
return None, None
#================================================================================
# メイン関数
#================================================================================
def main():
# ロギング設定の初期化
setup_logging()
# 設定ファイルのパス
config_path = Path(__file__).resolve().parent.parent / 'def' / (Path(__file__).stem + '.yaml')
transport_config = load_transport_config(config_path)
try:
for line in sys.stdin:
line = line.strip()
if line == "":
logging.info("Empty line detected, stopping.")
break
if line.startswith("recipient="):
recipient = line.split("recipient=")[-1]
if "@" not in recipient:
print("action=DUNNO\n")
logging.error(f"{recipient}: action=DUNNO, Invalid email address")
continue
recipient_domain = '@' + recipient.split("@")[-1]
service, rng = match_domain(transport_config, recipient_domain)
if service:
selected_number = random.randint(1, rng)
print(f"action=FILTER {service}{selected_number}:\n")
logging.info(f"{recipient}: action=FILTER {service}{selected_number}:")
else:
print("action=DUNNO\n")
logging.info(f"{recipient}: action=DUNNO")
sys.stdout.flush()
break
except Exception as e:
logging.error(f"Error processing request: {e}")
sys.exit(1)
if __name__ == "__main__":
main()
/etc/postfix/userprogram/def/check_policy_service.yaml
check_policy_services:
- docomo-smtp:
domains:
- '@docomo\.ne\.jp$'
- '@disneymobile\.ne\.jp$'
range: 4
- au-smtp:
domains:
- '@ezweb\.ne\.jp$'
- '@.+\.ezweb\.ne\.jp$'
range: 3
- softbank-smtp:
domains:
- '@softbank\.ne\.jp$'
- '@[dhtckrnsq]\.vodafone\.ne\.jp$'
range: 3
- gmail-smtp:
domains:
- "@gmail.com$"
range: 3
/etc/postfix/master.cf
policy_service unix - n n - - spawn
user=nobody argv=/etc/postfix/userprogram/bin/check_policy_service.py
docomo-smtp1 unix - - - - - smtp
docomo-smtp2 unix - - - - - smtp
docomo-smtp3 unix - - - - - smtp
docomo-smtp4 unix - - - - - smtp
au-smtp1 unix - - - - - smtp
au-smtp2 unix - - - - - smtp
au-smtp3 unix - - - - - smtp
softbank-smtp1 unix - - - - - smtp
softbank-smtp2 unix - - - - - smtp
softbank-smtp3 unix - - - - - smtp
gmail-smtp1 unix - - - - - smtp
gmail-smtp2 unix - - - - - smtp
gmail-smtp3 unix - - - - - smtp
/etc/postfix/main.cf
smtpd_recipient_restrictions = check_policy_service unix:private/policy_service
docomo-smtp1_destination_rate_delay=1s
docomo-smtp2_destination_rate_delay=1s
docomo-smtp3_destination_rate_delay=1s
docomo-smtp4_destination_rate_delay=1s
au-smtp1_destination_rate_delay=1s
au-smtp2_destination_rate_delay=1s
au-smtp3_destination_rate_delay=1s
softbank-smtp1_destination_rate_delay=1s
softbank-smtp2_destination_rate_delay=1s
softbank-smtp3_destination_rate_delay=1s
gmail-smtp1_destination_rate_delay=1s
gmail-smtp2_destination_rate_delay=1s
gmail-smtp3_destination_rate_delay=1s