メール
 Computer >> コンピューター >  >> ソフトウェア >> メール

メール検証サービスでFlaskのユーザー認証を強化する方法

現代のデジタル社会において、オンラインセキュリティは極めて重要であり、その中核を担うのがユーザー認証です。

メールアドレスを使った認証は、ユーザー登録やログインで最も広く利用されている手法の一つです。しかし、登録時に偽のメールアドレスや無効なメールアドレスが入力される可能性があり、必ずしも信頼できるとは言えません。これはセキュリティリスクや不正行為につながる恐れがあります。そこで役立つのが、メール検証サービス(Email Validation Service)です。

このチュートリアルでは、メール検証サービスを活用して、ユーザー登録時のメールアドレス検証プロセスを自動化する方法を解説します。

このAPIは、メールアドレスの構文・ドメイン・メールボックスをチェックするだけでなく、使い捨てメールアドレスや危険なメールアドレスの検出にも対応しています。

このAPIをアプリケーションに統合することで、有効かつ本物のメールアドレスのみをユーザー登録に使用できるようになり、アプリケーションのセキュリティを高めることができます。

前提条件

チュートリアルを始める前に、以下の要件を満たしていることを確認してください。

  • Pythonの実用的な知識があること
  • システムにPython 3.8以上がインストールされていること
  • Flask、Flask Blueprint、Requestsの基礎知識があること

仮想環境のセットアップ方法

コーディングを始める前に、必要なツールとライブラリがすべて揃っていることを確認しましょう。クリーンで分離された環境を保つため、venvを使って仮想環境を作成します。

まずプロジェクトディレクトリを作成し、ターミナルでそのディレクトリに移動します。

mkdir email-validation
cd email-validation

次のコマンドで、envという名前の仮想環境を作成します。

python -m venv env

現在のPythonには、仮想環境を作成するためのvenvライブラリが標準で同梱されています。

仮想環境は以下のようにアクティブ化します。

source env/bin/activate

注意:Windows環境の場合は、source env/Scripts/activateを使用して環境をアクティブ化してください。

ターミナルのプロンプトに(env)と表示されれば、仮想環境がアクティブになっています。

メール検証APIの使い方

メール検証は、ユーザー認証が必要なWebアプリケーションにとって不可欠なプロセスであり、実装方法はさまざまあります。

その一つが、emailvalidation.ioのようなメール検証サービスの利用です。このAPIを使うと、開発者はメールアドレスの構文が正しいか、ドメインが存在するか、メールボックスがメッセージを受信できるかをチェックして検証できます。

このAPIには、さまざまなニーズに応じた複数の料金プランが用意されています。無料プランでは最大100件のメールアドレスを検証でき、テスト用途には十分です。有料プランは月額9.99ドルからで、より多くのリクエスト数、追加機能、高速なレスポンスが提供されます。

このセクションでは、APIのエンドポイントにGETリクエストを送信し、検証対象のメールアドレスをパラメータとして渡すPython関数を作成します。

APIリクエストの認証のため、リクエストと一緒にAPIキーも渡す必要があります。先に進む前に、emailvalidation.ioでアカウントを作成してAPIキーを取得してください。アカウント作成後、ダッシュボードにリダイレクトされます。APIキーは黒くハイライトされた領域に表示されています。

GETリクエストを送信するために、仮想環境にrequestsライブラリをインストールします。

pip install requests

次に、test.pyファイルを作成し、以下のコードを記述します。

import requests
from requests.structures import CaseInsensitiveDict

def is_valid(email: str):
    url = f"https://api.emailvalidation.io/v1/info?email={email}"
    headers = CaseInsensitiveDict()
    headers["apikey"] = "your-api-key-here"
    response = requests.get(url, headers=headers)
    return response.json()

print(is_valid("support@emailvalidation.io"))
print(is_valid("venip42579@jdsdhak.com"))

is_valid関数はメールアドレスを引数として受け取り、そのメールアドレスを含むURLを構築してemailvalidation.ioのAPIを呼び出します。requests.structuresモジュールのCaseInsensitiveDictクラスを使うことで、大文字小文字を区別しないキーを持つ辞書を作成し、リクエストヘッダーにAPIキーを設定しています。最後に、関数からJSONレスポンスを返します。

最後に、異なるメールアドレスを指定してis_valid関数を2回呼び出し、有効なメールアドレス(support@emailvalidation.io)と無効なメールアドレス(venip42579@jdsdhak.com)の両方を検証できることを確認します。

実行結果:

{
  "email": "support@emailvalidation.io",
  "user": "support",
  "tag": "",
  "domain": "emailvalidation.io",
  "smtp_check": true,
  "mx_found": true,
  "did_you_mean": "",
  "role": true,
  "disposable": false,
  "score": 0.64,
  "state": "deliverable",
  "reason": "valid_mailbox",
  "free": false,
  "format_valid": true,
  "catch_all": "None"
}
{
  "email": "venip42579@jdsdhak.com",
  "user": "venip42579",
  "tag": "",
  "domain": "jdsdhak.com",
  "smtp_check": false,
  "mx_found": false,
  "did_you_mean": "",
  "role": false,
  "disposable": false,
  "score": 0.64,
  "state": "undeliverable",
  "reason": "invalid_mx",
  "free": false,
  "format_valid": true,
  "catch_all": "None"
}

レスポンスに含まれる各キーの詳細については、公式ドキュメントを参照してください。emailvalidation.ioからのJSONレスポンスに基づいてメールアドレスの有効性を判断するには、以下のフィールドを確認します。

  1. format_validtrueの場合、メールアドレスの形式は正しいです。falseの場合、そのメールアドレスは無効です。
  2. mx_foundtrueの場合、ドメインに少なくとも1つのMXレコードが見つかっています。falseの場合、ドメインが無効です。
  3. smtp_checktrueの場合、メールアドレスには有効なメールボックスが存在します。falseの場合、メールボックスが無効です。
  4. state:メールアドレスの現在の状態。値は「deliverable」(配信可能)または「undeliverable」(配信不可能)です。

そこで、JSONオブジェクトの代わりに真偽値を返すように、is_valid関数を以下のように修正できます。

import requests
from requests.structures import CaseInsensitiveDict

def is_valid(email: str):
    url = f"https://api.emailvalidation.io/v1/info?email={email}"
    headers = CaseInsensitiveDict()
    headers["apikey"] = "your-api-key-here"
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        json_resp = response.json()
        format_valid = json_resp["format_valid"]
        mx_found = json_resp["mx_found"]
        smtp_check = json_resp["smtp_check"]
        state = json_resp["state"]
        return format_valid and mx_found and smtp_check and state == "deliverable"
    return False

print(is_valid("support@emailvalidation.io"))
print(is_valid("venip42579@jdsdhak.com"))

実行結果:

True
False

次のセクションでは、この関数を使ってユーザー登録時にメールアドレスを検証する方法を見ていきます。

Flaskで基本的なユーザー認証をセットアップする方法

このセクションでは、Flaskで基本的なユーザー認証をセットアップする手順を説明します。ここでは、基本的なユーザー認証の実装方法を解説した以前の記事のコードを使用します。

まず、GitHubリポジトリからemail-validationフォルダへコードを取得しましょう。

git init
git remote add origin https://github.com/ashutoshkrris/Flask-User-Authentication.git
git pull origin main

注意:この場合、git clone https://github.com/ashutoshkrris/Flask-User-Authentication.git .コマンドは、ディレクトリが空ではないため実行できません。

次に、アプリケーションを実行するために必要な依存関係が記載されたrequirements.txtファイルがあります。以下のコマンドで依存関係をインストールします。

pip install -r requirements.txt

すべての依存関係をインストールしたら、プロジェクトに必要な環境変数を追加します。プロジェクトにはすべての環境変数を含む.envファイルがあります。以下のコマンドを実行して、.envファイルからすべての環境変数を読み込みます。

source .env

次に、データベースを作成します。このプロジェクトはFlask-Migrateを使用しているため、以下のコマンドで簡単にデータベースを作成できます。

python manage.py db init
python manage.py db migrate
python manage.py db upgrade

これで、以下のコマンドでアプリケーションを実行できます。

python manage.py run

アプリケーションが起動したら、ブラウザでhttps://localhost:5000/loginにアクセスして確認できます。

プロジェクト構造について

プロジェクトフォルダ内には、ソースコードを格納するsrcフォルダと、ユニットテストを格納するtestsフォルダがあります。

さらに、アプリケーションの設定が含まれるconfig.pyファイルや、Flask-CLIを使ってアプリケーションの実行・テスト用コマンドを定義するmanage.pyファイルもあります。その他、前述の.envrequirements.txtなどのファイルも含まれています。

srcフォルダの中には、accountscoretemplatesstaticという4つのサブフォルダがあります。templatesフォルダにはHTMLファイルが、staticフォルダにはCSS・画像・JavaScriptなどの静的ファイルが格納されています。残る2つのフォルダaccountscoreは、Flask Blueprintの仕組みを採用しており、アプリケーションの各部分に対応するコードをそれぞれ含んでいます。

Flaskアプリケーションの実装について詳しく知りたい方は、関連チュートリアルを参照してください。

Flaskアプリにメール検証サービスを統合する方法

現時点では、有効かどうかにかかわらず、任意のメールアドレスを使ってアプリケーションに登録できてしまいます。

しかし、ランダムなメールアドレスや誤ったメールアドレスがデータベースに蓄積されるのは望ましくありません。そこで、ユーザーを登録する前にメールアドレスを検証しておくのが良い考えです。メールアドレスが有効であれば、問題なくユーザー登録を進められます。

まず、公開されないようにEmail ValidationのAPIキーを.envファイルに追加します。

export SECRET_KEY=fdkjshfhjsdfdskfdsfdcbsjdkfdsdf
export DEBUG=True
export APP_SETTINGS=config.DevelopmentConfig
export DATABASE_URL=sqlite:///db.sqlite
export FLASK_APP=src
export FLASK_DEBUG=1
export API_KEY=your-api-key-here

your-api-key-hereを実際のAPIキーに置き換えてください。次に、以下のコマンドを再度実行して環境変数を読み込みます。

source .env

続いて、srcフォルダ内のaccountsサブフォルダにutils.pyファイルを作成します。このファイルには、メールアドレスを検証するユーティリティ関数を記述します。以下のコードを追加してください。

import requests
from requests.structures import CaseInsensitiveDict
from decouple import config

def is_valid(email: str):
    url = f"https://api.emailvalidation.io/v1/info?email={email}"
    headers = CaseInsensitiveDict()
    headers["apikey"] = config("API_KEY")
    response = requests.get(url, headers=headers)
    if response.status_code == 200:
        json_resp = response.json()
        format_valid = json_resp["format_valid"]
        mx_found = json_resp["mx_found"]
        smtp_check = json_resp["smtp_check"]
        state = json_resp["state"]
        return format_valid and mx_found and smtp_check and state == "deliverable"
    return False

前述の通り、is_valid()関数はメールアドレスの有効性を示す真偽値を返します。重要なのは、この関数ではAPIキーをハードコーディングせず、環境変数から取得している点です。

次に、forms.pyファイル内のRegisterFormクラスには、validateメソッドがあります。このメソッドは、登録処理中にユーザーが送信した入力データの検証を担当します。

以前は、このメソッドはメールアドレスがすでに登録済みかどうか、パスワードが一致しているかどうかだけをチェックしていました。しかし今回は、メールアドレスが有効かどうかをチェックする検証を追加できます。修正後のvalidateメソッドは以下のようになります。

...
from src.accounts.utils import is_valid
...
class RegisterForm(FlaskForm):
    ...
    def validate(self):
        initial_validation = super(RegisterForm, self).validate()
        if not initial_validation:
            return False
        if not is_valid(self.email.data):
            self.email.errors.append("Email is invalid")
            return False
        user = User.query.filter_by(email=self.email.data).first()
        if user:
            self.email.errors.append("Email already registered")
            return False
        if self.password.data != self.confirm.data:
            self.password.errors.append("Passwords must match")
            return False
        return True

validateメソッドでは、self.email.data(つまりユーザーのメールアドレス)が有効でない場合、self.email.errorsリストにエラーメッセージを追加し、Falseを返します。これはユーザーデータが無効であることを意味します。

これで、アプリケーションを実行して登録を試みると、動作を実際に確認できます。有効なケースと無効なケースの両方のデモを試してみてください。

メール検証サービスのその他の活用例

ユーザー登録時のメールアドレス検証以外にも、メール検証サービスにはさまざまな活用シーンがあります。主な例を紹介します。

  1. メールリストのクリーニング:メール検証サービスを使えば、無効・存在しない・危険なメールアドレスを削除してメールリストを整理できます。これにより、メールの到達率が向上し、意図した受信者に確実に届くようになります。
  2. 不正行為の防止:偽アカウントの作成や不正注文といった不正行為の検出にも活用できます。こうした活動に関連するメールアドレスを検証することで、不正行為を未然に防ぐことができます。
  3. マーケティングキャンペーンの強化:メールアドレスが有効かつアクティブであることを保証することで、メールの到達率が上がり、メールマーケティングキャンペーン全体のパフォーマンス向上につながります。

全体として、メール検証サービスは、ユーザーデータの正確性と妥当性の確保、不正行為の防止、ユーザー体験の向上に役立つ強力なツールです。

まとめ

メール検証サービスは、ユーザーのメールアドレス確認が必要なあらゆるアプリケーションにとって強力なツールです。エラーを防ぎ、ユーザーの入力データが正しいことを保証するためにも、メールアドレスの有効性確認は不可欠です。

この記事では、Pythonでemailvalidation.ioのAPIを使ってメールアドレスを検証する方法を学びました。また、不正行為の検出やメールマーケティングなど、メール検証サービスのその他の潜在的な活用例についても理解しました。

アプリケーションにメール検証サービスを実装することで、ユーザー体験を改善し、データの正確性と鮮度を維持することができます。

参考リソース

  • Blueprintを使ってFlaskアプリを整理する方法
  • Flaskアプリにメール認証(本人確認)をセットアップする方法
  • emailvalidation.io 公式ドキュメント
  1. Gmailアカウントに署名(シグネチャ)を追加・編集する方法

    Gmailの署名(シグネチャ)とは?メールの末尾に署名を添えることで、メール全体によりプロフェッショナルな印象を与えることができます。一度署名を設定しておけば、その後に送信するすべてのメールへ自動的に挿入されるためとても便利です。署名の内容は名前だけでも構いませんし、電話番号を添えるのも一般的です。顧客や取引先と頻繁にやり取りするビジネスユーザーなら、住所や携帯番号など、相手からの連絡に役立つ情報を追加しておくとより効果的です。もちろんGmailでも署名機能を利用できます。設定手順は非常にシンプルなので、以下のステップに沿って進めてみましょう。署名を設定するメリット署名を登録しておく最大のメリ

  2. Gmailエラー#707「サーバーエラーが発生し、メールが送信されませんでした」の直し方

    Gmailで「おっと…サーバーエラーが発生し、メールが送信されませんでした(#707)」というエラーメッセージが表示される場合、Gmailクライアントがサーバーと正常な接続を確立できていないことが主な原因です。本来、メールはまずGmailのサーバーへ送信され、その後、宛先として指定した相手のアカウントに保存される仕組みです。この通信の流れに何らかの障害が起きると、このエラーが発生します。この問題は特にFirefoxブラウザで発生しやすいことが知られており、いくつかの有効な対処法があります。最も一般的なのは「Avastのメール署名機能を無効化する」という方法で、その他にも新規メッセージを作成して