1. 「500人に個別メールを手作業で送っていた」という悩み
私が勤める会社では、毎月末に顧客500人へ個別の請求書・お知らせメールを送信する業務がありました。Excelで管理された顧客リストを開き、1件1件コピーペーストしてOutlookで送信する作業です。所要時間は毎月約4時間。担当者が変わるたびにミスが発生し、同じ顧客に2通届いたり、送信漏れが起きたりしていました。
「これ、絶対に自動化できるはず」と思いながらも、Pythonのコードを書いたことはありませんでした。そこでClaude Codeを使ってみることにしました。Claude Codeはプログラミングの知識がなくても、日本語で要件を伝えるだけでコードを生成してくれるAIコーディングアシスタントです。
手作業 vs Claude Code自動化 比較表
| 項目 | 手作業(従来) | Claude Code自動化(改善後) |
|---|---|---|
| 1件あたりの時間 | 約30秒(コピペ・確認) | 0.3秒(自動送信) |
| 500件の処理時間 | 約4時間 | 約5分(コード生成含む) |
| ヒューマンエラー | 送信漏れ・重複送信が月2〜3件 | ゼロ(ログで完全管理) |
| 送信ログ管理 | 手動Excelで記録(忘れがち) | 自動でExcelに記録 |
| 担当者依存 | 高い(熟練者が必要) | なし(誰でも実行可能) |
2. Claude Codeへの最初のプロンプト
Claude Codeを開いて、まず現状を日本語で説明しました。Claude Codeは自然言語で要件を伝えると、適切なPythonコードを自動生成してくれます。最初のプロンプトはこんな感じです。
プロンプト例 1
列構成は「顧客名」「メールアドレス」「担当者名」「送信フラグ」です。
このExcelを読み込んで、各顧客に個別メールを送信するPythonスクリプトを作ってください。
メールの件名は「【重要】〇〇様への月次ご報告」という形式で顧客名を差し込んでください。
本文も顧客名と担当者名を差し込んだ個別文章にしてください。
Gmailを使ってSMTP送信したいです。
送信済みかどうかをExcelの「送信フラグ」列に自動で記録してください。
Claude Codeはこのプロンプトを受け取り、数秒でPythonコードを生成してくれました。Claude Codeが出力したコードには、Excelの読み込み・メール差し込み・SMTP送信・送信ログ記録まで全ての要素が含まれていました。
「以下のPythonスクリプトを生成しました。実行前にGmailのアプリパスワードを取得し、環境変数に設定してください。スクリプトは送信フラグが空白の行だけを処理するため、途中で止まっても続きから再開できます。」
3. Claude Codeが生成した最初のコード
以下がClaude Codeが生成したPythonコードです。私はPythonをほとんど書いたことがありませんでしたが、Claude Codeのコードは読めばロジックがわかるように書かれていました。
# Claude Codeが生成したコード: Excelリストからメール一括送信 import os import smtplib import pandas as pd from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from datetime import datetime import time # ── 設定(環境変数から安全に読み込む)──────────────── GMAIL_USER = os.environ["GMAIL_USER"] # 送信元アドレス GMAIL_PASS = os.environ["GMAIL_APP_PASS"] # Gmailアプリパスワード EXCEL_PATH = "customers.xlsx" # メール本文テンプレート SUBJECT_TMPL = "【重要】{customer_name}様への月次ご報告" BODY_TMPL = """ {customer_name} 様 いつも大変お世話になっております。 担当の{staff_name}でございます。 今月の月次レポートをお送りいたします。 ご不明点がございましたら、お気軽にご連絡ください。 何卒よろしくお願い申し上げます。 """ def send_email(to_addr: str, subject: str, body: str) -> bool: """1通のメールを送信して成否を返す""" msg = MIMEMultipart() msg["From"] = GMAIL_USER msg["To"] = to_addr msg["Subject"] = subject msg.attach(MIMEText(body, "plain", "utf-8")) try: with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server: server.login(GMAIL_USER, GMAIL_PASS) server.send_message(msg) return True except Exception as e: print(f" [ERROR] {to_addr}: {e}") return False def main(): # Excelを読み込む df = pd.read_excel(EXCEL_PATH) print(f"顧客リスト読み込み完了: {len(df)}件") sent_count = 0 fail_count = 0 for idx, row in df.iterrows(): # 送信フラグが「済」の行はスキップ if row["送信フラグ"] == "済": continue customer_name = row["顧客名"] to_addr = row["メールアドレス"] staff_name = row["担当者名"] subject = SUBJECT_TMPL.format(customer_name=customer_name) body = BODY_TMPL.format(customer_name=customer_name, staff_name=staff_name) print(f"送信中: {customer_name} ({to_addr})") success = send_email(to_addr, subject, body) # 送信結果をExcelに記録 now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") df.at[idx, "送信フラグ"] = "済" if success else "失敗" df.at[idx, "送信日時"] = now if success: sent_count += 1 else: fail_count += 1 time.sleep(0.5) # レート制限対策 # 結果をExcelに保存 df.to_excel(EXCEL_PATH, index=False) print(f"\n完了: 送信成功 {sent_count}件 / 失敗 {fail_count}件") if __name__ == "__main__": main()
Claude Codeが生成したこのコードを実行したときのターミナル出力がこちらです。
顧客リスト読み込み完了: 500件 送信中: 株式会社A様 (sample-a@example.com) 送信中: 山田花子様 (yamada@example.com) 送信中: 鈴木商事株式会社様 (suzuki@example.com) ... (498件省略) 送信中: 最後の顧客様 (last@example.com) 完了: 送信成功 498件 / 失敗 2件 失敗分は「送信フラグ」列に「失敗」と記録されました。
Claude Codeを使った結果
- コード生成にかかった時間: 約2分
- 500件の送信にかかった時間: 約4分30秒
- 送信ログがExcelに自動記録: 完全自動
- 従来の手作業4時間が: 約7分に短縮
4. 「添付ファイルも付けてほしい」と追加指示したら即座に対応
最初のコードで基本機能は完成しましたが、実際には請求書PDFを添付して送りたいという要件がありました。Claude Codeに追加でプロンプトを打ちました。Claude Codeは前の会話の文脈を保持しているので、追加指示を送るだけでコードを拡張してくれます。
プロンプト例 2
各顧客に対応するPDFファイルを添付して送りたいです。
ファイル名のルールは「請求書_顧客名_202604.pdf」という形式です。
PDFが存在しない場合は添付なしで送信し、ログにも「PDF未作成」と記録してください。
Claude Codeは30秒ほどで添付ファイル対応版のコードを出力しました。Claude Codeが追加・変更した箇所だけを差分で説明してくれるので、どこが変わったかが一目でわかります。
import os import smtplib import pandas as pd from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email import encoders from datetime import datetime import time GMAIL_USER = os.environ["GMAIL_USER"] GMAIL_PASS = os.environ["GMAIL_APP_PASS"] EXCEL_PATH = "customers.xlsx" PDF_DIR = "./invoices/" # PDFが置かれているフォルダ YEAR_MONTH = "202604" # 請求月 def send_email_with_attachment(to_addr: str, subject: str, body: str, pdf_path: str) -> tuple: """メールを送信(PDFがあれば添付する)""" msg = MIMEMultipart() msg["From"] = GMAIL_USER msg["To"] = to_addr msg["Subject"] = subject msg.attach(MIMEText(body, "plain", "utf-8")) pdf_attached = False if pdf_path and os.path.exists(pdf_path): with open(pdf_path, "rb") as f: part = MIMEBase("application", "octet-stream") part.set_payload(f.read()) encoders.encode_base64(part) part.add_header("Content-Disposition", f"attachment; filename={os.path.basename(pdf_path)}") msg.attach(part) pdf_attached = True try: with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server: server.login(GMAIL_USER, GMAIL_PASS) server.send_message(msg) return True, pdf_attached except Exception as e: print(f" [ERROR] {to_addr}: {e}") return False, False def main(): df = pd.read_excel(EXCEL_PATH) for idx, row in df.iterrows(): if row["送信フラグ"] == "済": continue customer_name = row["顧客名"] to_addr = row["メールアドレス"] staff_name = row["担当者名"] # PDFファイルのパスを組み立てる pdf_name = f"請求書_{customer_name}_{YEAR_MONTH}.pdf" pdf_path = os.path.join(PDF_DIR, pdf_name) subject = f"【重要】{customer_name}様への月次ご報告" body = f"{customer_name} 様\n\nお世話になっております。担当の{staff_name}です。\n月次レポートを添付いたします。" success, pdf_ok = send_email_with_attachment(to_addr, subject, body, pdf_path) now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") df.at[idx, "送信フラグ"] = "済" if success else "失敗" df.at[idx, "送信日時"] = now df.at[idx, "PDF添付"] = "済" if pdf_ok else "PDF未作成" time.sleep(0.5) df.to_excel(EXCEL_PATH, index=False) print("送信完了。ログをExcelに保存しました。") if __name__ == "__main__": main()
5. HTMLメールに変更してほしいとClaude Codeに頼んだら
次に「テキストメールではなく、会社ロゴ入りのHTMLメールにしたい」という追加要件が出ました。HTMLのコーディングは私には難しいですが、Claude Codeに頼むだけで対応してくれました。
プロンプト例 3
緑色(#107C41)を基調にしたデザインで、
ヘッダーに「Aurant Technologies」のロゴテキストを入れてください。
テキスト版も同時に送れるようにMIMEAlternativeを使ってください。
from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText def build_html_body(customer_name: str, staff_name: str) -> str: """HTMLメール本文を生成する""" return f""" <!DOCTYPE html> <html lang="ja"> <head><meta charset="UTF-8"></head> <body style="font-family: sans-serif; background: #f9f9f9; margin:0; padding:20px;"> <div style="max-width:600px; margin:0 auto; background:white; border-radius:12px; overflow:hidden; box-shadow:0 2px 12px rgba(0,0,0,0.08);"> <div style="background:#107C41; padding:24px 32px;"> <h1 style="color:white; font-size:20px; margin:0;">Aurant Technologies</h1> </div> <div style="padding:32px;"> <p style="font-size:16px; color:#333;"><strong>{customer_name} 様</strong></p> <p style="color:#555; line-height:1.8;"> いつも大変お世話になっております。<br> 担当の<strong>{staff_name}</strong>でございます。<br><br> 今月の月次レポートをお送りいたします。<br> ご不明点はお気軽にご連絡ください。 </p> </div> <div style="background:#f0faf4; padding:16px 32px; font-size:12px; color:#888;"> © 2026 Aurant Technologies </div> </div> </body> </html>""" def send_html_email(to_addr: str, subject: str, customer_name: str, staff_name: str) -> bool: msg = MIMEMultipart("alternative") msg["From"] = GMAIL_USER msg["To"] = to_addr msg["Subject"] = subject # テキスト版(受信環境がHTML非対応の場合のフォールバック) text_body = f"{customer_name} 様\n\nお世話になっております。{staff_name}です。\n月次レポートをお送りします。" html_body = build_html_body(customer_name, staff_name) msg.attach(MIMEText(text_body, "plain", "utf-8")) msg.attach(MIMEText(html_body, "html", "utf-8")) with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server: server.login(GMAIL_USER, GMAIL_PASS) server.send_message(msg) return True
6. 大量送信用にSendGrid対応版もClaude Codeに頼んだ
Gmailには1日500通の上限があります。1万件以上を送りたい場合はSendGridなどのサービスが必要です。Claude Codeに「SendGridに切り替えたバージョンも作って」と頼んだら、すぐに対応してくれました。
プロンプト例 4
sendgrid ライブラリを使って同じ機能を実現するコードを書いてください。
APIキーは環境変数 SENDGRID_API_KEY から取得してください。
import os from sendgrid import SendGridAPIClient from sendgrid.helpers.mail import Mail, Attachment, FileContent, FileName, FileType SENDGRID_KEY = os.environ["SENDGRID_API_KEY"] FROM_EMAIL = os.environ["FROM_EMAIL"] def send_via_sendgrid(to_addr: str, subject: str, html_body: str, pdf_path: str = None) -> bool: """SendGrid経由でHTMLメール(添付ファイルオプション)を送信""" message = Mail( from_email=FROM_EMAIL, to_emails=to_addr, subject=subject, html_content=html_body ) # PDF添付(存在する場合のみ) if pdf_path and os.path.exists(pdf_path): with open(pdf_path, "rb") as f: import base64 encoded = base64.b64encode(f.read()).decode() attachment = Attachment( FileContent(encoded), FileName(os.path.basename(pdf_path)), FileType("application/pdf") ) message.attachment = attachment try: sg = SendGridAPIClient(SENDGRID_KEY) response = sg.send(message) return response.status_code == 202 except Exception as e: print(f"SendGrid エラー: {e}") return False
7. エラーハンドリングと送信ログ管理を強化してもらった
実際の運用では、ネットワークエラーや無効なメールアドレスなど様々なエラーが発生します。Claude Codeに「エラーが発生したときに管理者に通知してほしい」と伝えると、エラー通知機能も自動的に追加してくれました。
プロンプト例 5
「送信失敗が{N}件発生しました」というアラートメールを送ってください。
また、全件送信完了後に送信サマリー(成功件数・失敗件数・所要時間)を
管理者メールとExcelログシートの両方に記録してください。
import time from datetime import datetime import pandas as pd import openpyxl from openpyxl.styles import PatternFill, Font ADMIN_EMAIL = os.environ["ADMIN_EMAIL"] FAIL_THRESHOLD = 5 # この件数以上失敗でアラート送信 def main(): df = pd.read_excel(EXCEL_PATH) start_time = time.time() sent_count = fail_count = 0 alert_sent = False for idx, row in df.iterrows(): if row["送信フラグ"] == "済": continue success = send_email_with_attachment( row["メールアドレス"], row["顧客名"], row["担当者名"] ) if success: sent_count += 1 df.at[idx, "送信フラグ"] = "済" else: fail_count += 1 df.at[idx, "送信フラグ"] = "失敗" # 失敗が閾値を超えたら管理者に通知 if fail_count >= FAIL_THRESHOLD and not alert_sent: send_admin_alert(fail_count) alert_sent = True elapsed = round(time.time() - start_time, 1) # ログシートにサマリーを追記 write_summary_log(sent_count, fail_count, elapsed) # 管理者にサマリーメール送信 summary_body = f"""送信完了サマリー 実行日時: {datetime.now().strftime('%Y-%m-%d %H:%M')} 送信成功: {sent_count}件 送信失敗: {fail_count}件 所要時間: {elapsed}秒 """ send_email(ADMIN_EMAIL, "メール一括送信完了レポート", summary_body) df.to_excel(EXCEL_PATH, index=False) print(summary_body)
Claude Codeへのプロンプトは「こういう機能を追加してください」という自然な日本語でOKです。技術用語を知らなくても、「エラーが起きたら通知してほしい」「失敗した分だけ記録したい」という言い方で伝われば、Claude Codeが適切な実装方法を選んでコードを生成します。
8. 環境構築もClaude Codeに教えてもらった
Pythonが初めての方にとって、環境構築は最初のハードルです。Claude Codeはコードの生成だけでなく、実行環境の構築手順も日本語で丁寧に説明してくれます。
プロンプト例 6
Gmailのアプリパスワードの設定方法、
環境変数の設定方法をWindows向けに教えてください。
1. ライブラリのインストール
コマンドプロンプトで以下を実行してください:
pip install pandas openpyxl sendgrid
2. Gmailアプリパスワードの取得
Googleアカウント → セキュリティ → 2段階認証を有効化 → アプリパスワードで「メール」を選択して発行
3. 環境変数の設定(Windows)
コマンドプロンプトで実行:
setx GMAIL_USER "your@gmail.com"
setx GMAIL_APP_PASS "xxxx xxxx xxxx xxxx"
9. 導入事例:3社のClaude Code活用体験
毎月800件の賃貸物件の更新案内メールを担当スタッフが手作業で送っていました。Claude Codeに「更新月の3ヶ月前に自動送信したい」と伝えたところ、Excelの更新日列から3ヶ月後の顧客を抽出して自動送信するスクリプトを生成してくれました。Claude Codeのおかげで月20時間の作業がゼロになりました。
送信漏れゼロ
Claude Code活用
決算期に200社への決算書類・請求書メール送付がボトルネックになっていました。Claude Codeに「顧客ごとに異なるPDFを添付して送りたい」と伝えると、ファイル名のルールを学習してマッチングロジックを自動生成。Claude Codeが生成したコードで従来3日かかっていた作業が2時間に短縮されました。
PDF自動マッチング
Claude Code生成
10. よくある質問(FAQ)
Claude Codeを使った
メール自動化を今すぐ試しませんか?
顧客リストのExcelを見せてもらうだけで、
Claude Codeが最適なメール自動化スクリプトを提案します。
無料相談で具体的なプロンプト設計までサポートします。