本ページはプロモーションが含まれています。

毎朝決まった時刻にスクレイピングして、結果をメールで受け取りたい。スクリプトは書けたのに、どこで動かすかで迷っていませんか。cronでメール通知をするだけなら、高いVPSも常駐も要りません。ただし、契約してから「メールが届かない」で詰まることがあります。原因は25番ポートの扱いです。この記事では、今の書き方である「587番+SMTP認証」のPythonコードを紹介します。あわせて、エックスサーバー・VPS・自宅PCの選び方を2026年11月時点の料金と受付状況つきで整理します。

1日1回のメール通知を置く場所:手元PC・エックスサーバー・VPS・自宅回線の比較

「1日1回動かして、結果をメールで送る」処理に必要なものは3つだけです。決まった時刻に起動する仕組み(cron)、Pythonが動く環境、そしてメールを送り出せる経路です。常駐プロセス(ずっと起動し続けるプログラム)も、root権限(サーバー全体の管理者権限)も要りません。この前提で各環境を比べると、次のようになります。

置き場所

cron

常駐

root権限

メール送信で詰まりやすい点

止まる条件

手元のPC

OSの機能(タスクスケジューラ等)で可

可

あり

自宅回線では25番ポートでの外部送信が塞がれていることが多い(OP25B)

電源断・スリープ・OS更新後の再起動・回線断

共有レンタルサーバー

サーバーパネルから設定

不可

なし

契約にメール機能があれば、同じサーバーのSMTPを使える

実行時間・リソースの制限で強制終了される

VPS

自分でcrontabを書く

可

あり

25番ポートの扱いは事業者・契約ごとに確認が必要

OS・セキュリティ更新を放置した場合や、事業者側のメンテナンス

自宅サーバー(ミニPC等)

自分で設定

可

あり

手元PCと同じくOP25Bの影響を受ける

停電・回線断・ハードウェア故障

OP25B(Outbound Port 25 Blocking)は、家庭向けの回線から外部のメールサーバーへ25番ポートで直接送るのを止める仕組みです。迷惑メール対策として導入されています。自宅で動かすなら、25番ポートで直接送る書き方は最初から捨てるのが前提です。

料金と新規受付の状況(2026年11月時点)

2026年10月中旬には、Linuxカーネルの脆弱性(CVE-2026-99999)への対応で、国内の主要VPSが相次いで新規受付を止めました。今は「安いかどうか」より先に「今日契約できるか」を確認する必要があります。

サービス

種別

料金(調査時点)

無料お試し

新規受付

エックスサーバー

共有

スタンダード36ヶ月契約で月額990円(税込)。2026年11月4日18時7分時点の通常料金

10日間

受付中。最大30%オフのキャンペーン(10月5日〜11月4日)は終了

さくらのレンタルサーバ

共有

スタンダード月額500円〜

2週間

受付中

mixhost

共有

ライト月額495円〜。キャンペーンではライト12ヶ月で初回月額594円(税込)

記載なし

受付中

シン・レンタルサーバー

共有

2026年9月1日に値上げ。11月時点でキャンペーンなし

10日間

受付中

ConoHa WING

共有

—

なし

2026年10月24日から停止中(再開時期未定)

ConoHa VPS

VPS

まとめトク36ヶ月で月額326円、1ヶ月単位なら月額460円、時間課金1.3円/時〜(最安は1コア・メモリ512MB・SSD30GB)

なし(時間課金に最低利用期間なし)

10月23日に再開後、24日から再び停止

さくらのVPS

VPS

2GBプラン月額1,594円〜

2週間

10月23日に石狩、10月30日に大阪の一部プランで再開

KAGOYA CLOUD VPS

VPS

最安月額770円(2Core・2GB・NVMe200GB)。日額課金あり

なし(日額課金で試せる)

10月27日に再開

XServer VPS

VPS

9月1日に値上げ。4GBプランは1ヶ月契約で月額2,640円

無料VPSは7月10日から受付停止

9月17日から停止中。11月中に再開予定(確定ではない)

お名前.com VPS

VPS

2Core・1GB・SSD100GBで月額985円

記載なし

—

表の数値は2026年11月時点の各社公開情報をまとめたものです。料金も受付状況も短期間で変わっています。申し込む直前に、各社の公式サイトで料金ページと「お知らせ」欄を必ず確認してください。長期契約の割引は初回だけで、更新時に高くなるケースもあります。初回価格と一緒に「更新後の月額」も見ておくと安心です。

以前は25番ポートで直接送信、今は587番+SMTP認証で書く

以前の書き方:localhostの25番ポートに投げる

VPSや自宅サーバーでは、以前はサーバー内にメール配送ソフト(MTA)を入れていました。Pythonからは localhost に送るだけ、という書き方がよく使われていました。

import smtplib
from email.mime.text import MIMEText

msg = MIMEText("本文", "plain", "utf-8")
msg["Subject"] = "日次レポート"
msg["From"] = "送信元アドレス"
msg["To"] = "送信先アドレス"

with smtplib.SMTP("localhost") as smtp:  # 既定は25番ポート
    smtp.sendmail(msg["From"], [msg["To"]], msg.as_string())

この書き方は、サーバー内のMTAが25番ポートで相手のメールサーバーへ直接届けられる前提で成り立っています。自宅回線ではOP25Bに止められます。VPSでも25番ポートの扱いは事業者や契約によって異なります。さらに、自前のMTAから届けたメールは、送信ドメインの認証設定が揃っていないと迷惑メール扱いされやすくなります。「1日1通の通知」のために抱える手間としては重すぎます。

今の書き方:既存のメールアカウントのSMTPに587番で認証して渡す

今は、すでに持っているメールアカウントのSMTPサーバーを使います。587番ポート(メール投稿用のサブミッションポート)に接続し、STARTTLSで暗号化してからログインして送ります。宛先への配送はそのメールサーバーが担当するので、実行場所が自宅でもVPSでも同じコードで動きます。

import smtplib
import ssl
from email.message import EmailMessage

msg = EmailMessage()
msg["Subject"] = "日次レポート"
msg["From"] = "送信元アドレス"
msg["To"] = "送信先アドレス"
msg.set_content("本文")

context = ssl.create_default_context()
with smtplib.SMTP("smtp.example.com", 587, timeout=30) as smtp:
    smtp.starttls(context=context)
    smtp.login("username", "パスワード")
    smtp.send_message(msg)

以前の書き方からの変更点は3つです。

  • EmailMessage を使う:MIMEText を組み立てる代わりに、set_content() で本文を入れます。日本語の文字コードは自動で処理されます。EmailMessage はPython 3.6で標準ライブラリに追加されました。
  • starttls() に検証つきのコンテキストを渡す:ssl.create_default_context() を使うと、サーバー証明書を検証したうえで暗号化します。
  • send_message() で送る:ヘッダーの From/To から送信元と宛先を読み取ります。as_string() で文字列にする手順は不要です。

SMTPサーバー名・ポート・ユーザー名は、メールアカウントの「メールソフト設定」欄などに書かれている値を使います。レンタルサーバーの契約にメール機能があれば、サーバーパネルで確認できます。587番は外部への直接配送ではなく、自分のアカウントへの「投稿」です。OP25Bの対象外として扱われるのが一般的ですが、念のため次の確認スクリプトで実際に試してください。

契約したらまず確認:その環境から587番に出られるか

さくらのVPSやConoHa VPSの25番ポートの扱いについて、今回の調査では2026年11月時点の公式な制限内容を確認できませんでした。そのため具体的な条件は書きません。公式ドキュメントで確かめるのが前提ですが、もっと確実なのは実際に接続してみることです。さくらのVPSやエックスサーバーの無料お試し期間、あるいはConoHa VPSやKAGOYA CLOUD VPSの時間・日額課金を使えば、本契約の前に次のスクリプトを実行できます。

import socket
import sys

host = sys.argv[1] if len(sys.argv) > 1 else "smtp.example.com"

for port in (25, 587):
    try:
        with socket.create_connection((host, port), timeout=10) as sock:
            banner = sock.recv(200).decode(errors="replace").strip()
            print(f"{port}: 接続できた  {banner}")
    except OSError as e:
        print(f"{port}: 接続できない  {e}")

このスクリプトは、自分が使うSMTPサーバーに25番と587番でつながるかを1回ずつ試すだけです。メールは送りません。python3 check_smtp.py smtp.example.com のように実行して、587番で 220 から始まる応答が返れば、送信経路は確保できています。25番が「接続できない」でも、587番が通れば問題ありません。

毎朝動かすPythonスクリプト一式(requests+EmailMessage)

実行環境

  • Python 3(EmailMessage を使うため3.6以上)。サーバー上で python3 --version を実行して確認します。
  • 追加パッケージは requests だけです。メール送信・robots.txtの解釈・設定ファイルの読み込みは標準ライブラリで済みます。
python3 -m pip install --user requests
python3 -m pip show requests

共有レンタルサーバーには root権限がありません。そのため --user をつけて自分のホームディレクトリにインストールします。今回の用途では特定バージョンへの固定は不要です。pip show で表示されたバージョンを控えておけば、後で挙動が変わったときの手がかりになります。

設定ファイル:パスワードをスクリプトに書かない

cronから起動したプログラムには、ログイン時に読み込まれる環境変数が渡らないことがあります。そこで認証情報は、本人だけが読める設定ファイルに分けておきます。

; /home/username/.config/daily_report.ini
[smtp]
host = smtp.example.com
port = 587
user = username
password = (メールアカウントのパスワード)
from_addr = (送信元のメールアドレス)
to_addr = (受け取りたいメールアドレス)
chmod 600 /home/username/.config/daily_report.ini

本体:取得してメールで送る

import configparser
import re
import smtplib
import ssl
import time
import urllib.robotparser
from datetime import datetime
from email.message import EmailMessage
from pathlib import Path

import requests

CONFIG_PATH = Path("/home/username/.config/daily_report.ini")
TARGET_URL = "https://example.com/news"
ROBOTS_URL = "https://example.com/robots.txt"
USER_AGENT = "daily-report-bot/1.0 (+https://example.com/)"


def load_config():
    config = configparser.ConfigParser()
    config.read(CONFIG_PATH, encoding="utf-8")
    return config["smtp"]


def allowed_by_robots():
    rp = urllib.robotparser.RobotFileParser()
    rp.set_url(ROBOTS_URL)
    rp.read()
    return rp.can_fetch(USER_AGENT, TARGET_URL)


def fetch_summary():
    res = requests.get(TARGET_URL, headers={"User-Agent": USER_AGENT}, timeout=30)
    res.raise_for_status()
    res.encoding = res.apparent_encoding
    m = re.search(r"<title>(.*?)</title>", res.text, re.S)
    title = m.group(1).strip() if m else "(titleなし)"
    return f"ステータス: {res.status_code}\nページタイトル: {title}\nサイズ: {len(res.content)} bytes"


def send_mail(cfg, subject, body):
    msg = EmailMessage()
    msg["Subject"] = subject
    msg["From"] = cfg["from_addr"]
    msg["To"] = cfg["to_addr"]
    msg.set_content(body)

    context = ssl.create_default_context()
    with smtplib.SMTP(cfg["host"], cfg.getint("port"), timeout=30) as smtp:
        smtp.starttls(context=context)
        smtp.login(cfg["user"], cfg["password"])
        smtp.send_message(msg)


def main():
    cfg = load_config()
    started = time.monotonic()
    today = datetime.now().strftime("%Y-%m-%d")

    try:
        if not allowed_by_robots():
            subject = f"[日次] {today} 取得をスキップ"
            body = "robots.txtで取得が許可されていないため、取得しませんでした。"
        else:
            subject = f"[日次] {today} 取得成功"
            body = fetch_summary()
    except Exception as e:
        subject = f"[日次] {today} 取得失敗"
        body = f"{type(e).__name__}: {e}"

    elapsed = time.monotonic() - started
    body += f"\n\n処理時間: {elapsed:.1f} 秒"
    send_mail(cfg, subject, body)


if __name__ == "__main__":
    main()

ブロックごとの役割は次のとおりです。

  1. 定数:取得先のURL、robots.txtの場所、名乗るUser-Agentをまとめています。User-Agentに連絡先のURLを入れておくと、相手のサイト管理者が問い合わせ先を判断できます。
  2. load_config():先ほどの設定ファイルから [smtp] セクションを読みます。スクリプト本体にはパスワードを持たせません。
  3. allowed_by_robots():標準ライブラリの urllib.robotparser でrobots.txtを読み、対象URLへのアクセスが許可されているかを判定します。
  4. fetch_summary():ページを1回だけ取得します。timeout=30 は、相手が応答しないときに処理が止まらないようにするためです。raise_for_status() で4xx/5xxを例外にして、失敗メールの側に回します。中身の解析はここを書き換えて使ってください。
  5. send_mail():前の節で示した587番+STARTTLS+ログインの送り方です。
  6. main():取得に失敗しても例外を握りつぶさず、「取得失敗」の件名でメールを送ります。毎日動かすうえで大事なのは、「メールが来ない=止まっている」と判断できる状態にしておくことです。本文の最後には処理時間を入れています。この数値が自分の環境での実測値になり、日々のメールで推移を追えます。

取得先サイトへの配慮:robots.txt・利用規約・アクセス間隔

  • robots.txt:上のコードのように毎回確認し、許可されていなければ取得しません。
  • 利用規約:robots.txtで許可されていても、規約で自動取得を禁止しているサイトがあります。最初に一度読み、規約が変わっていないか定期的に見直してください。
  • アクセス間隔:このスクリプトは1日1回、1ページ1リクエストです。複数ページを取る場合は、1件ごとに time.sleep() で数秒以上空けてください。対象を必要なページだけに絞ることも大切です。並列でまとめて取りに行く書き方はしません。
  • ログインや制限の回避はしない:会員限定ページ、アクセス制限、ボット対策がかかっているページは、自動取得の対象から外します。公式のAPIや配信(RSSなど)があるなら、そちらを使います。

cron登録と毎日動かし続ける条件:エックスサーバー・VPS・自宅PCが止まる場面

cronの書き方(共通)

0 7 * * * /usr/bin/python3 /home/username/scripts/daily_report.py >> /home/username/logs/daily_report.log 2>&1
  • 0 7 * * *:毎日7時0分に実行します。
  • /usr/bin/python3:cronでは PATH がログイン時と違うことがあるため、Pythonはフルパスで書きます。実際のパスは、SSHでログインできる環境なら which python3 で確認します。
  • >> ... 2>&1:通常の出力もエラーもログファイルに追記します。メール自体が送れなかったときの手がかりになります。

エックスサーバーのような共有レンタルサーバーでは、サーバーパネルのcron設定画面に、上の「時刻」と「コマンド」を分けて入力します。最短実行間隔はサービスごとに決まっていますが、1日1回ならどのサービスでも問題になりません。

環境ごとの「止まる条件」と向いている人

環境

止まる条件

向いているケース

手元のPC

電源を切る、スリープに入る、OS更新後に再起動したまま、回線が落ちる

まず動作を試したい段階。毎日の運用には向かない

共有レンタルサーバー(エックスサーバー等)

実行時間やCPU使用量が上限を超えると強制終了される。常駐はできない

処理が数分以内で終わる1日1回の通知。メール機能つきなら送信経路もそろう

VPS(ConoHa VPS・さくらのVPS・KAGOYA等)

OSやセキュリティの更新を自分でしないと危険。事業者側のメンテナンスで止まることもある。25番ポートの扱いは契約前に確認

常駐が必要、処理が長い、Pythonのバージョンを自由に選びたい

自宅サーバー

停電、回線断、機器の故障。外出中は復旧できない

家庭内の機器と連携したい処理。メールは587番+外部SMTPが前提

手元のPCで動かす場合は、Windows Updateの再起動でタスクが動かなかった日がないか確認しましょう。更新の確認方法は Windows 11 11月更新 確認方法|更新の履歴とOSビルド にまとめています。共有レンタルサーバーで処理が長くなってきた場合は、強制終了の条件と分割の書き方を レンタルサーバー cron 強制終了|30分バッチ 26年11月 で解説しています。

どこを選べば送信で詰まらないか

  1. 処理が短く、1日1回で足りる:共有レンタルサーバーで十分です。エックスサーバー(10日間無料)やさくらのレンタルサーバ(2週間無料)なら、お試し期間中にcron登録から587番での送信まで確認できます。
  2. 常駐や長時間の処理が必要:VPSを選びます。2026年11月時点で新規受付をしているのは、KAGOYA CLOUD VPS(10月27日再開)と、さくらのVPSの一部リージョン・プランです。ConoHa VPSとXServer VPSは新規受付を停止しています。契約できたら、まず確認スクリプトで587番を試してください。
  3. 自宅で動かしたい:25番ポートでの直接送信は使えない前提で、最初から587番+既存のメールアカウントで書きます。

関連する選択肢

毎日決まった時刻にスクリプトを動かすだけなら、共有のレンタルサーバーでも足ります。cronが使えるプランを選べば、自分でOSを管理する必要はありません。

レンタルサーバー エックスサーバー

※ 広告を含みます(A8.net)。リンク経由でお申し込みがあった場合、手数料を受け取ることがあります。

送信で詰まらない環境の結論:1日1回なら共有サーバーのcron+587番

毎朝の処理結果をメールで送るだけなら、常駐もroot権限も要りません。まずは共有レンタルサーバーのcronで十分です。エックスサーバーはスタンダード36ヶ月契約で月額990円(2026年11月4日時点)、さくらのレンタルサーバはスタンダード月額500円〜で、どちらも無料お試し期間があります。メールは、以前のようにlocalhostの25番ポートへ投げる書き方をやめましょう。EmailMessage を使い、既存アカウントのSMTPへ587番+STARTTLS+認証で渡せば、自宅でもVPSでも同じコードで動きます。VPSは10月のカーネル脆弱性対応で受付状況が変わり続けているので、契約前に公式の「お知らせ」を確認してください。契約したら、587番に接続できるかを最初に試しましょう。失敗時も必ずメールを送る作りにしておけば、届かない日に止まっていると気づけます。