フォームで大量のスパムが送信される被害が報告されています


近日 a-blog cms へのフォームで、大量のスパムメールが送信されてしまう報告をいくつか受けております。 被害が発生している方は、以下対応策をいくつか用意していますので、大変お手数ですがご対応のほどお願いいたします。

reCAPTCHA以外の対策は、対応してもスパムが止まらない可能性がございますので、reCAPTCHAの導入をおすすめいたします。

reCAPTCHAの導入

お問い合わせ者が、ロボットか判断するGoogleの「reCAPTCHA」サービスと連携する方法がございます。 a-blog cms の拡張アプリとして用意されていますので、こちらご検討ください。

2021/12/07 19:50追記

reCAPTCHA拡張アプリに一部不具合がありましたので、 2021/12/07 19:50以前にダウンロードしている場合は、お手数ですが再度ダウンロードしてファイルを置き換えをお願いいたします。

ダウンロードURL: https://github.com/appleple/acms-recaptcha/raw/master/build/recaptcha.zip

reCAPTCHAの拡張アプリに関する詳細はGitHubページをご確認ください。


フォームのURL変更

攻撃はURL指定でされる可能性が高いです。根本的な解決にはなりませんが、ひとまず攻撃をさけるためにはフォームのURLを変更ください。

攻撃者のIPアドレスでブロック

.htaccessなどで、攻撃者のIPアドレスをブロックします。ただし複数のIPアドレスで攻撃される可能性が高いのでイタチごっこになってしまう可能性がございます。 order allow,deny allow from all deny from xxx.xxx.xxx.xxx deny from yyy.yyy.yyy.yyy

CMSのアップデート

2.11, 2.10, 2.9, 2.8 のそれぞれのバージョンでセキュリティフィックスをリリースいたしました。これは攻撃方法によって管理画面のフォーム設定の「入力チェック・変換」が効かない場合がある問題が修正されております。CMSアップデート後、フォーム設定の「入力チェック・変換」項目を確認・設定ください。


フォーム設定の修正

フォームのセキュリティ設定について、ドキュメントを更新させていただきました。できるだけ、こちらで紹介されている設定にしていただくようにお願いします。


今後とも a-blog cms をよろしくお願いいたします。

拡張アプリの reCAPTCHA に不具合がみつかりました。


reCAPTCHA拡張アプリに不具合が見つかりました。

2021年12月07日 19:50以前にダウンロードしてされた方は、お手数ですが再度ダウンロードしてファイルを置き換えをお願いいたします。

GitHub: https://github.com/appleple/acms-recaptcha

ダウンロードURL: https://github.com/appleple/acms-recaptcha/raw/master/build/recaptcha.zip

この度はご迷惑をおかけしてしまい申し訳ございません。 ご対応のほどよろしくお願いいたします。

フォームでエントリーなどのカスタムフィールドやグローバル変数を渡すカスタマイズ


フォームの自由度の高さは a-blog cms の特長のひとつです。このエントリーでは、そのカスタマイズの一例として、ユーザーがフォームに入力したフィールド以外の変数の渡し方を解説します。エントリーフィールド、カテゴリーフィールド、ブログフィールドなどのカスタムフィールド、クエリ変数やグローバル変数をフォームの変数として扱えるようにします。

変数を追加するテンプレートの場所

フォームを入力するテンプレートに追加します。公式テーマの site や beginner では /contact/form/input.html になります。初期の入力画面と step#reapply に共通でインクルードされ、追加した変数を途中のステップで表示することもできるようになります。

エントリーフィールドをフォームの変数として追加する

エントリーにフォームがあり、そのエントリーのカスタムフィールドを渡したい場合には、下記のようにコードを追加します。

<!-- BEGIN_MODULE Entry_Field -->

<input type="hidden" name="area" value="{area}">
<input type="hidden" name="field[]" value="area">

<input type="hidden" name="price" value="{price}">
<input type="hidden" name="field[]" value="price">

<!-- END_MODULE Entry_Field -->

area 及び price というエントリーカスタムフィールドがフォームに渡されます。

カテゴリー、ブログ、ユーザーのカスタムフィールドをフォームの変数として追加する

カテゴリー、ブログのカスタムフィールドの場合も、エントリーの場合と同様、フォームに渡すことができます。また、ログインしているユーザーに関しては、ユーザーのカスタムフィールドを渡すこともできます。その場合 ctx="uid/%{SESSION_USER_ID}" を User_Field モジュールに追加します。

<!-- BEGIN_MODULE User_Field ctx="uid/%{SESSION_USER_ID}" -->

<input type="hidden" name="gender" value="{gender}">
<input type="hidden" name="field[]" value="gender">

<!-- END_MODULE User_Field -->

gender というユーザーカスタムフィールドがフォームに渡されます。もちろん {name} や {mail} などのフィールドも渡せるので、ログインしたユーザーであればフォームの項目にいちいち入力させないといったカスタマイズも可能です。

グローバル変数をフォームの変数として追加する

グローバル変数はそのままでメールの返信テンプレートに使用できます。公式テーマでも %{BLOG_NAME} などのグローバル変数が使われています。拡張したグローバル変数の場合も同様です。しかし、グローバル変数もフォームの変数として追加する必要があるケースがあります。

フォームへのリンクにクエリストリングを持たせておけば、どの媒体、どのページからの遷移であるかを確認するなどの使い方ができます。また、Google スプレッドシートとの連携はフォームの件数や項目が多い場合の管理に便利です。

グローバル変数をフォームの変数として追加する書き方は次のとおりです。

<input type="hidden" name="global_var" value="%{GLOBAL_VAR}">
<input type="hidden" name="field[]" value="global_var">

以上、今回は type="hidden" で変数を渡すケースを解説しましたが、もちろん type="text" 等でフォームの項目の初期値として様々な変数を扱い、ユーザー側で変更可能にするカスタマイズも可能です。ぜひ、取り入れてみてください。

カテゴリーを SELECT で検索するフォームを作るには


カテゴリーリストモジュール( Category_List )を利用して、検索フォームを作る実装について書いてみます。カテゴリーリストモジュールは、子カテゴリーがあった際に入れ子で表示ができるようにするために少し複雑な動きをしています。

まずは、カテゴリーリストモジュールのスニペットを確認してみます。

カテゴリーリストモジュールのスニペット

<!-- BEGIN_MODULE Category_List -->
<div class="acms-margin-bottom-medium">
@include("/admin/module/setting.html")
  <!-- BEGIN category:loop --><!-- BEGIN ul#front -->
  <ul class="acms-list-group">
  <!-- END ul#front --><!-- BEGIN li#front -->
    <li><!-- END li#front --><!-- BEGIN category:veil -->
      <a href="{url}" class="acms-list-group-item">{name}<!-- BEGIN amount:veil -->
        <span class="acms-badge acms-float-right">{amount}</span><!-- END amount:veil -->
      </a><!-- END category:veil --><!-- BEGIN li#rear -->
    </li><!-- END li#rear --><!-- BEGIN ul#rear -->
  </ul>
  <!-- END ul#rear --><!-- END category:loop -->
</div>
<!-- END_MODULE Category_List -->

エントリーリストモジュール であれば、<ul> は entry:loop の外にあるのが一般的ですが、カテゴリーリストモジュール は、category:loop の内側に <ul> があるのでカスタマイズする際には注意が必要です。

最終的な表示されるフォームのHTML

上記のようなスニペットを利用して、以下のような HTML ができるようなことを考えてみます。

<form action="" method="POST">
  <select name="cid">
    <option>全て</option>
    <option value="2">お知らせ</option>
    <option value="3">製品情報</option>
    <option value="4">会社概要</option>
    <option value="6">お問い合わせ</option>
    <option value="7">採用情報</option>
    <option value="8">物件情報</option>
  </select>
  <input type="submit" name="ACMS_POST_2GET" value="検索">
</form>

フォームとしては実際には、以下のようになります。

スニペットを改造してみる

普通に考えると、まずは以下のように実装するのではないかと思います。

<form action="" method="POST">
  <!-- BEGIN_MODULE Category_List -->
  <select name="cid">
    <option value="">全て</option>
  <!-- BEGIN category:loop -->
    <option value="{cid}">{name}</option>
  <!-- END category:loop -->
  </select>
  <!-- END_MODULE Category_List -->
<input type="submit" name="ACMS_POST_2GET" value="検索">
</form>

しかし、これを a-blog cms のテンプレートに書くと、残念ながら以下のような結果になります。今回、どうしてそうなるのかという説明は省きますが、必要のない   <option value=""></option> を表示させないようにすることを追記することを考えます。

<select name="cid">
  <option value="">全て</option>
  <option value=""></option>
  <option value="2">お知らせ</option>
  <option value=""></option>
  <option value="3">製品情報</option>
  <option value=""></option>
  <option value="1">家庭用製品</option>
  <option value=""></option>
  <option value="5">業務用製品</option>
  <option value=""></option>
  <option value=""></option>
  <option value=""></option>
  <option value="4">会社概要</option>
  <option value=""></option>
  <option value="6">お問い合わせ</option>
  <option value=""></option>
  <option value="7">採用情報</option>
  <option value=""></option>
  <option value="8">物件情報</option>
  <option value=""></option>
  <option value=""></option>
</select>

空の optoin を非表示にする

方法としては IFブロックを利用して表示されて欲しくない部分は出ないようにします。例えば、{cid} が空ではない時という条件を設定したり

  <!-- BEGIN category:loop -->
    <!-- BEGIN_IF [{cid}/nem]-->
      <option value="{cid}">{name}</option>
    <!-- END_IF -->
  <!-- END category:loop -->

子カテゴリーがあるものがあった時に子カテゴリーを非表示にしたい場合を考え、階層の変数 {level} が 1 のものだけを表示する

  <!-- BEGIN category:loop -->
    <!-- BEGIN_IF [{level}/eq/1]-->
      <option value="{cid}">{name}</option>
    <!-- END_IF -->
  <!-- END category:loop -->

このような設定をします。

selected="selected" の処理

検索結果のページで select が選択したところが選択したままになるようにするためには、option に selected="selected" をつける必要があります。

今回は、option の中に IFブロックを書き、グローバル変数 %{CID} とカテゴリーリストモジュール内の {cid} との比較を行います。

<!-- BEGIN_IF [%{CID}/eq/{cid}] --> selected="selected"<!-- END_IF -->

最終的なカテゴリーリストモジュールの実装

  1. スニペットを改造してみる
  2. 空の optoin を非表示にする
  3. selected="selected" の処理

を実装し、人が読みやすいようにテンプレートを書くと以下のようになります。

<form action="" method="POST">
  <!-- BEGIN_MODULE Category_List -->
  <select name="cid">
    <option value="">全て</option>
  <!-- BEGIN category:loop -->
    <!-- BEGIN_IF [{level}/eq/1]-->
    <option value="{cid}"
      <!-- BEGIN_IF [%{CID}/eq/{cid}] -->
        selected="selected"
      <!-- END_IF -->
    >{name}</option>
    <!-- END_IF -->
  <!-- END category:loop -->
  </select>
  <!-- END_MODULE Category_List -->
<input type="submit" name="ACMS_POST_2GET" value="検索">
</form>

a-blog cms のテンプレートは、必要がないところは消える仕様になっていますが、消える部分の外にある改行だけ有効になってしまうことから上記を実行すると

<form action="" method="POST">
  
  <select name="cid">
    <option value="">全て</option>
  
    
  
    
    <option value="2"
      
    >お知らせ</option>
    
  
    
  
    
    <option value="3"
      
    >製品情報</option>


(以下略)

のように空白だらけのソースコードになります。HTML として表側では改行や空白は関係ないので、このままでも構いませんが綺麗にした例もご紹介しておきます。

<form action="" method="POST">
  <!-- BEGIN_MODULE Category_List -->
  <select name="cid">
    <option value="">全て</option>
  <!-- BEGIN category:loop --><!-- BEGIN_IF [{level}/eq/1]-->  <option value="{cid}"<!-- BEGIN_IF [%{CID}/eq/{cid}] --> selected="selected"<!-- END_IF -->>{name}</option>
  <!-- END_IF --><!-- END category:loop --></select>
  <!-- END_MODULE Category_List -->
<input type="submit" name="ACMS_POST_2GET" value="検索">
</form>

この HTML であれば、以下のようなソースコードになります。

<form action="" method="POST">
  
  <select name="cid">
    <option value="">全て</option>
    <option value="2">お知らせ</option>
    <option value="3">製品情報</option>
    <option value="4">会社概要</option>
    <option value="6">お問い合わせ</option>
    <option value="7" selected="selected">採用情報</option>
    <option value="8">物件情報</option>
  </select>
  
<input type="submit" name="ACMS_POST_2GET" value="検索">
</form>

今回は、特殊なカテゴリーリストのループをシンプルにする方法と、現在表示している selected の対応についての紹介でした。

お問い合わせフォームの設定を最適化する

目標


お問い合わせなどのフォームが入力された時、お問い合わせした人や管理者へ送信する確認メールをカスタマイズしましょう。


解説使用テーマbeginner

Before

After

目次

  1. フォームの仕組み
  2. テンプレートの形式でメールを受け取る
  3. オリジナルの件名・本文を入力してメールを受け取る

フォームの仕組み


初期設定のサイトマップでは、フォームの機能を体験するためのお問い合わせページ( http://example.com/contact/ )を用意しています。まずはこのページでフォームの仕組みについて学んでいきましょう。


お問い合わせページでは、入力する項目を下図のように設定しています。


お問い合わせフォーム

通常このフォームから送信された内容は、サイト管理者のメールアドレスに届くようにしなければなりません。また、入力されたアドレス宛へ確認メールが必要な場合もあります。まずはフォーム管理画面から、それらのアドレスを設定しましょう。


  1. 管理ボックスから [管理ページ] ボタンをクリックする
  2. サイドメニュー内 [フォーム] をクリックする
  3. リスト内「お問い合わせフォーム」右側の [変更] ボタンをクリックする


フォームの管理画面では、「基本設定」「入力チェック・変換」「一般メール設定」「管理者宛メール設定」を編集することができます。


基本設定



基本設定では、最初にフォームIDとフォーム名を定めています。


フォームID
制作するサイトによっては、お問い合わせフォームや募集フォームなど複数のフォームを設置することがあります。それらを区別する任意の英数字がフォームIDです。モジュールIDと同じくフォームIDはテンプレートと管理画面で合わせて設定されており、これによってフォームの設定や投稿データを管理できます。

テーマ「beginner2020」では、お問い合わせフォームのフォームIDはテンプレート側で contactForm と指定されているため、基本設定画面からも同じIDを使用しています。


入力チェック・変換



フォームの任意の項目に対して、「入力必須」や「最大文字数」などの条件を指定することができます。テンプレートを編集する必要があります。

しかし今回のチュートリアルでは管理画面のみでできることを学習するため、この機能について作業することはありません。


一般メール設定


一般メール設定では、フォームに入力した方へ送信するメールを管理することができます。



基本的には、メールの件名、本文について管理画面から直接入力し、通常のメールフォームと同様に「To」で送信先のメールアドレスを、「From」で送信元のメールアドレスを指定します。その他にも、通常のメールの設定と同じようにCc・Bcc・Reply-To の設定ができます。

「一般メール設定」の「From」は概ねサイト管理者になるので、自分のメールアドレスを入力しておくと良いでしょう。


From(自分のメールアドレス)

また件名、本文を入力していない場合は、a-blog cms 側で用意しているテンプレートの形式が採用されます。上図の件名ファイル、本文ファイルの項目に記入されている「/contact/form/subject.txt」「/contact/from/body.html」などは、そのテンプレートが置いてある場所へのパスになっています。


管理者宛メール設定


管理者宛メール設定では、フォームの管理者宛へ送信されるメールを管理することができます。



構成は一般メール設定と同じです。メールの件名、本文について管理画面から直接入力し、通常のメールフォームと同様に「AdminTo」で送信先のメールアドレスを、「AdminFrom」で送信元のメールアドレスを指定できるようになっています。

こちらでは送信先をサイト管理者にする必要があるので、「AdminTo」へ自分のメールアドレスを入力しておきましょう。


AdminTo(自分のメールアドレス)

一般メール設定のFrom・管理者宛メール設定のAdminToに自分のメールアドレスを入れたら、フォームの設定を保存してください。


テンプレートの形式でメールを受け取る


まずは a-blog cms が用意しているテンプレートの形式でメールを受け取ってみましょう。

お問い合わせページを開き、各項目に入力してください。入力する内容は自由ですが、内容確認メールも同時に受け取るために「お客様情報」のメールアドレス欄には自分のメールアドレスを設定してください。



フォーム送信後、設定/入力した自分のメールアドレス宛に確認メールが届きます。メール内容を見てみしましょう。


管理者宛メール内容

管理者宛メール内容


一般メール内容

一般メール内容


フォーム設定で指定されているメールのテンプレートファイルに沿って、フォームから入力された情報が表示されました。


以上がフォームを送信した時の流れになります。これらを踏まえて、次はフォーム設定から件名と本文を変更してみましょう。


オリジナルの件名・本文を入力してメールを受け取る


一般メール設定


まずは一般メール設定について、以下のように件名・本文を入力しましょう。


件名(優先)


【株式会社▲▲】お問い合わせありがとうございます

本文(優先)


この度はお問い合わせいただき、ありがとうございました。
以下の内容で送信しました。

+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-+:-+:-+:-+:-+

受付日時:%{Y}年%{n}月%{j}日 %{H}:%{i}:%{s}
通番 : {serialNumber}

■お問い合わせ情報

ご用件    : {description}[raw]
お問い合わせ内容:
{inquiry}[raw]


■お客様情報

会社名    : {organization}[raw]
お名前    : {family-name}[raw] {given-name}[raw]
メールアドレス: {email}
お電話番号  : {tel}
ご住所    : 〒{postal-code} {address-level1} {address1} {address2}


+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-+:-+:-+:-+:-+

今後とも株式会社▲▲をよろしくお願いいたします。

この本文について、{変数} で示されている部分には実際にメールで入力された内容が表示されます。この変数の値についてはテンプレート側で指定しているものになるので、ブラウザ上での変更はできません。したがって、フォームから入力された内容を本文中に表示したい場合は、該当の値を上記のソースから直接コピー&ペーストしてお使いください。

少し踏み込んで学習をすると、こちらでは %{変数} の形で「グローバル変数」が、{変数}[オプション] の形で「校正オプション」が利用されています。それぞれの機能の詳細については、以下のリンクの解説をご覧ください。

管理者宛メール設定

管理者宛メール設定については、以下のように入力します。


件名(優先)


お問い合わせを受信しました

本文(優先)


弊社公式HPよりお問い合わせを受信しました。
担当者は迅速な対応をお願いします。

+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-+:-+:-+:-+:-+

受付日時:%{Y}年%{n}月%{j}日 %{H}:%{i}:%{s}
通番 : {serialNumber}

■お問い合わせ情報

ご用件    : {description}[raw]
お問い合わせ内容:
{inquiry}[raw]


■お客様情報

会社名    : {organization}[raw]
お名前    : {family-name}[raw] {given-name}[raw]
メールアドレス: {email}
お電話番号  : {tel}
ご住所    : 〒{postal-code} {address-level1} {address1} {address2}

+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-:+:-+:-+:-+:-+:-+

入力内容を保存したら再度お問い合わせを送信し、自分のメールフォームより受信したメールの内容を確認しましょう。


管理者宛メール内容

管理者宛メール内容


送信者宛メール内容

送信者宛メール内容


入力した件名や本文が表示され、また変数で記入した部分にフォームの入力内容が反映されていればチュートリアルの目標は達成です。