コンテンツにスキップ

メール送信

概要

「メール送信API」を使用するとメールを送信できます。

なお、APIキーのユーザのメールアドレス、または「Mail.json」のSupportFromが設定されている必要があります。

注意事項

  1. バージョン1.5.0.0から1.5.2.0のプリザンターには、添付ファイルが破損する不具合があります。当該の不具合はバージョン1.5.3.0で修正されています。添付ファイル付きのメール送信を使用する場合は、バージョン1.5.0.0から1.5.2.0のプリザンターを使用しないでください。

事前準備

APIの操作を行う前にAPIキーの作成を実施してください。

リクエスト

下記のリクエスト形式で、JSONデータを送信します。

設定項目 値
HTTPメソッド POST
Content-Type application/json
文字コード UTF-8
URL http://{サーバ名}/api/items/{レコードID}/OutgoingMails/Send 1
Body 以下のJSONデータを参考のこと

JSONデータの必須項目

項目 必須 備考
ApiVersion 〇
ApiKey 〇
From -
To -
Cc -
Bcc -
Title 〇
Body -
Attachments - 以下のプロパティを設定してください。
Name : ファイル名
Base64 : 添付ファイルをBase64エンコードした文字列
ContentType : コンテンツタイプ
リクエストサンプル
{
     "ApiVersion": 1.1,
     "ApiKey": "[設定したAPIキー]",
     "From": "[Mail.jsonのFixedFrom値]",
     "To": "[受信側メールアドレス]",
     "Cc": "[受信側Ccメールアドレス]",
     "Bcc": "[受信側Bccメールアドレス]",
     "Title": "メール送信APIのテストです",
     "Body": "メール送信APIのテストでメールを送信します。",
     "Attachments": [
         {
             "Name": "sample1.txt",
             "Base64": "c2FtcGxlMS50eHQ=...",
             "ContentType": "text/plain"
         },
         {
             "Name": "sample2.txt",
             "Base64": "c2FtcGxlMi50eHQ=...",
             "ContentType": "text/plain"
         }
     ]
}

FixedFrom値については、Mail.jsonを参照してください 。

レスポンス

下記の形式のJSONデータが返却され、メールが送信されます。

レスポンスサンプル
1
2
3
4
5
{
    "Id": <レコードID>,
    "StatusCode": 200,
    "Message": "メールを送信しました。"
}

サンプルコード

Note

コード内の【 ... 】は適宜修正してください。

1. 請求書の発行完了のCSVから、案件の担当者へ請求書のPDFを添付して送る

会計システムが出力した請求書の発行完了のCSVを1行ずつ読み、案件コードで案件管理のレコードを探して、担当者のメールアドレスへ請求書のPDFを添付して送ります。

実務での使いどころ

会計・契約・出荷など、外部のシステムで処理が終わったことを、関係するレコードの担当者へファイル付きで知らせる場面に使えます。標準の通知は、プリザンターでレコードを作成・更新したときなどに送るもので、外部のシステムの処理が終わったときをきっかけにはできません。また、その場で作ったファイルを添付することもできません。

事前準備

1:メールを送れるように、Mail.jsonを設定してください。送信元は、APIキーのユーザーのメールアドレス、またはMail.jsonのSupportFromです。

2:「案件管理」テーブル(期限付きテーブル)で、以下の項目を有効化してください。

項目コード 内容
分類A(ClassA) 案件コード
分類B(ClassB) 担当者のメールアドレス

3:発行完了のCSV(invoice_completed.csv、UTF-8)を用意します。

案件コード,請求書ファイル,請求金額,発行日
P-001,C:\invoices\invoice_P-001.pdf,1200000,2026/10/27

4:サンプルコードの【 】を書き替えてください。

Python
# ==========================================================
# 請求書の発行完了の通知:会計システムが出力した発行完了のCSVを1行ずつ読み、
# 案件コードで案件管理のレコードを探して、担当者のメールアドレスへ請求書のPDFを
# 添付して送ります(メール送信APIは、送るときにレコードのIDを指定します。ここでは見つけた案件のID)。
# ==========================================================
import base64
import csv
import sys
from pathlib import Path

import requests

# ===== 設定 =====
BASE_URL = "【URL】"
API_KEY = "【APIキー】"
PROJECT_SITE_ID = "【案件管理のサイトID】"
CODE_COLUMN = "ClassA"   # 案件コード
MAIL_COLUMN = "ClassB"   # 担当者のメールアドレス
INPUT_CSV = Path("./invoice_completed.csv")  # 1行目は見出し「案件コード,請求書ファイル,請求金額,発行日」


def api_post(path, payload=None):
    """Pleasanter APIへPOSTする。HTTPステータスとレスポンスのJSONを返す"""
    response = requests.post(
        f"{BASE_URL}{path}",
        json={"ApiVersion": 1.1, "ApiKey": API_KEY, **(payload or {})},
        headers={"Content-Type": "application/json"},
        timeout=60,
    )
    return response.status_code, response.json()


def find_project(code):
    """案件コードが一致する案件を探す。1件に決まらなければ None"""
    # 分類項目の絞り込みは、配列形式+ExactMatchMultipleでないと完全一致にならない
    view = {
        "ColumnFilterHash": {CODE_COLUMN: f'["{code}"]'},
        "ColumnFilterSearchTypes": {CODE_COLUMN: "ExactMatchMultiple"},
    }
    _, body = api_post(f"/api/items/{int(PROJECT_SITE_ID)}/get", {"View": view})
    rows = body.get("Response", {}).get("Data", [])
    return rows[0] if len(rows) == 1 else None


def send_notice(row):
    """1行分の通知を送る。失敗したら理由を返す(送れたら None)"""
    project = find_project(row["案件コード"])
    if project is None:
        return "案件が1件に決まりません"
    to = project.get("ClassHash", {}).get(MAIL_COLUMN, "")
    if not to:
        return "担当者のメールアドレスが空です"
    pdf = Path(row["請求書ファイル"])
    if not pdf.is_file():
        return f"請求書ファイルがありません({pdf})"
    status, body = api_post(f"/api/items/{project['IssueId']}/OutgoingMails/Send", {
        "To": to,
        "Title": f"【請求書発行】{row['案件コード']} {project['Title']}",
        "Body": f"{project['Title']} の請求書を発行しました。\n請求金額:{int(row['請求金額']):,}円\n発行日:{row['発行日']}",
        "Attachments": [{
            "Name": pdf.name,
            "Base64": base64.b64encode(pdf.read_bytes()).decode("ascii"),
            "ContentType": "application/pdf",
        }],
    })
    if status != 200 or body.get("StatusCode") != 200:
        return body.get("Message", f"HTTP {status}")
    return None


def main():
    with open(INPUT_CSV, encoding="utf-8-sig", newline="") as f:
        rows = [row for row in csv.DictReader(f) if row["案件コード"].strip()]
    failed = 0
    for row in rows:
        reason = send_notice(row)
        if reason:
            # 1行で失敗しても、残りの行は送る
            print(f"[NG] {row['案件コード']}: {reason}")
            failed += 1
        else:
            print(f"[OK] {row['案件コード']}: 送りました")
    # 失敗があれば終了コード 1 にして、呼び出し元で気付けるようにする
    if failed:
        sys.exit(1)


if __name__ == "__main__":
    main()

注記

  • メール送信APIは、items/{レコードID}/OutgoingMails/Sendのように、レコードのIDを指定して呼びます。このサンプルでは、案件コードで見つけた案件のIDを使います。
  • 添付ファイルは、Attachmentsに、ファイル名・Base64にした中身・コンテンツタイプを入れます。
  • 案件コードで案件が1件に決まらないとき(見つからない・同じコードが複数ある)、担当者のメールアドレスが空のとき、請求書ファイルが無いときは、その行を送らずに次の行へ進み、最後に終了コード1で終わります。
  • 案件コードは、配列形式の値とExactMatchMultipleで完全一致で探します。「P-001」で「P-0010」の案件を見つけることはありません。

エラー時の確認事項

対応バージョン

対応バージョン 内容
1.2.4.0 以降 Attachmentsを追加

関連情報


  1. {サーバ名}、{レコードID}の部分は、適宜、環境に合わせて編集してください。
    Pleasanter.netの場合は以下の形式になります。

    https://pleasanter.net/fs/api/items/{レコードID}/OutgoingMails/Send  
    
     ↩