LoginSignup
73
80

More than 5 years have passed since last update.

PHPで作るメールフォーム

Last updated at Posted at 2014-03-16

メールフォーム作成

以下のサイト様からソースコードを一部拝借しています。

3番目のエントリのPHPロジック部分は全然ダメなのですが、サッと作れるデザインとしてはなかなか気に入ったので…w

ソースコード

sendmailに渡す -f (Return-Path) は適切に指定してください。

<?php

/**
 * HTML特殊文字をエスケープする関数
 */
function h($str) {
    return htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
}

/**
 * RuntimeExceptionを生成する関数
 * http://qiita.com/mpyw/items/6bd99ff62571c02feaa1
 */
function e($msg, Exception &$previous = null) {
    return new RuntimeException($msg, 0, $previous);
}

/**
 * 例外スタックを配列に変換する関数
 * http://qiita.com/mpyw/items/6bd99ff62571c02feaa1
 */
function exception_to_array(Exception $e) {
    do {
        $msgs[] = $e->getMessage();
    } while ($e = $e->getPrevious());
    return array_reverse($msgs);
}

/* 変数の初期化 */
foreach (array('name', 'email', 'contents', 'token', 'confirm', 'execute') as $v) {
    $$v = trim(filter_input(INPUT_POST, $v));
}

/* セッションの初期化 */
session_name('ContactForm');
@session_start();
if (!isset($_SESSION['token'])) {
    $_SESSION['token'] = array();
}

/* 「確認」か「送信」のときのみ実行 */
if ($confirm or $execute) {
    try {
        // トークンをチェック
        if (!isset($_SESSION['token'][$token])) {
            throw e('フォームの有効期限が切れています。', $e);
        }
        // トークンを消費させる
        unset($_SESSION['token'][$token]);
        // 各項目チェック
        if ($name === '') {
            $e = e('名前を入力してください。', $e);
        }
        if ($email === '') {
            $e = e('メールアドレスを入力してください。', $e);
        } elseif (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
            $e = e('メールアドレスが不正です。', $e);
        }
        // 例外がここまでに1つでも発生していればスローする
        if (!empty($e)) {
            throw $e;
        }
        // 「送信」のとき
        if (
            $execute and
            !mb_internal_encoding('utf-8') ||
            !mail(
                'info@example.com',
                mb_encode_mimeheader('フォームからの送信', 'ISO-2022-JP-MS'),
                mb_convert_encoding($contents, 'ISO-2022-JP-MS'),
                implode("\r\n", array(
                    'Content-Type: text/plain; charset=ISO-2022-JP',
                    'From: ' . mb_encode_mimeheader($name, 'ISO-2022-JP-MS')
                             . ' <' . $email . '>',
                )),
                '-f info@example.com'
            )
        ) {
            throw e('メール送信でエラーが発生しました。', $e);
        }
    } catch (Exception $e) {
        // 最初の画面に戻す
        $confirm = $execute = '';
    }
}

/* 「最初」か「確認」のときのみ実行 */
if (!$execute) {
    // 値をダミーにしてトークンをキー部分に生成(最大10個まで保持)
    $_SESSION['token'] = array_slice(
        array($token = sha1(mt_rand()) => true) + $_SESSION['token'],
        0,
        10
    );
}

// ヘッダー送信
header('Content-Type: application/xhtml+xml; charset=utf-8');

?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja">
  <head>
    <title>Contact Form</title>
    <style type="text/css"><![CDATA[
      h1 {
        color: red;
        font-size: 18pt;
      }
      #contact-form th {
        background-color: #9bdbea;
        padding: 10px 20px;
      }
      #contact-form td {
        background-color: #f7f7ef;
        padding: 10px 20px;
      }
      #contact-form td input {
        width: 400px;
      }
      #contact-form td textarea {
        width: 400px;
      }
      form {
        display: inline;
      }
      #errmsg {
        background-color:#E7D3D6;
        border:3px solid #A55952;
        color:#944121;
        font-size:12px;
        margin:10px;
        padding:10px;
        text-align:left;
        width:400px;
      }
    ]]></style>
  </head>
  <body>
    <h1>コンタクトフォーム</h1>
<?php if (!empty($e)): ?>
    <div id="errmsg">
      <ul>
<?php foreach (exception_to_array($e) as $msg): ?>
        <li><?=$msg?></li>
<?php endforeach; ?>
      </ul>
    </div>
<?php endif; ?>
<?php if ($execute): ?>
    <p>送信しました。ご意見ありがとうございました。<br /><a href="">戻る</a></p>
<?php elseif ($confirm): ?>
    <p>この内容で送信しますか?</p>
    <p>
      <form action="" method="post">
        <table id="contact-form" border="1" cellpadding="0" cellspacing="0">
          <tr>
            <th>名前(必須)</th>
            <td><?=h($name)?></td>
          </tr>
          <tr>
            <th>メールアドレス(必須)</th>
            <td><?=h($email)?></td>
          </tr>
          <tr>
            <th>内容</th>
            <td><pre><?=
              $contents !== '' ?
              h($contents) :
              '<span style="color:red;">【未入力】</span>'
            ?></pre></td>
          </tr>
          <tr>
            <th colspan="2">
              <input type="hidden" name="name" value="<?=h($name)?>" />
              <input type="hidden" name="email" value="<?=h($email)?>" />
              <input type="hidden" name="contents" value="<?=h($contents)?>" />
              <input type="hidden" name="token" value="<?=h($token)?>" />
              <input type="submit" name="execute" value="送信" />
              <input type="submit" value="修正" />
            </th>
          </tr>
        </table>
      </form>
    </p>
<?php else: ?>
    <p>
      <form action="" method="post">
        <table id="contact-form" border="1" cellpadding="0" cellspacing="0">
          <tr>
            <th>名前(必須)</th>
            <td><input type="text" name="name" value="<?=h($name)?>" /></td>
          </tr>
          <tr>
            <th>メールアドレス(必須)</th>
            <td><input type="text" name="email" value="<?=h($email)?>" /></td>
          </tr>
          <tr>
            <th>内容</th>
            <td><textarea name="contents" rows="10"><?=h($contents)?></textarea></td>
          </tr>
          <tr>
            <th colspan="2"><input type="submit" name="confirm" value="確認" /></th>
          </tr>
        </table>
        <div><input type="hidden" name="token" value="<?=h($token)?>" /></div>
      </form>
    </p>
<?php endif; ?>
  </body>
</html>
73
80
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
73
80