in_arrayで送信したアドレスが存在するかチェックする

$sql = "select * from users";
			$stmt = $dbh2->query($sql);
			while($result = $stmt->fetch(PDO::FETCH_ASSOC)){
				$users[] = $result['username'];
			}

   			$sql2 = "select * from sends where username = '".$username."' order by sendtime desc";
			$stmt2 = $dbh2->query($sql2);

			while($result = $stmt2->fetch(PDO::FETCH_ASSOC)){
				$id[] = $result['mid'];
				$to = $result['destination'];
				if(in_array($to, $users)){
					$suc[] = "送信済み"; 
				} else {
					$suc[] = "宛先のアドレスが存在しません"; 
				}
				$destination[] = $to;
				$subject[] = $result['subject'];
				$sendtime[] = $result['sendtime'];
			}

			$i= 0;
			echo "<table>";
			foreach($destination as $value){
				echo "<tr><td> <img src=\"icon.png\"> <a href=\"?path=mailrp&inbox=".$id&#91;$i&#93;."\">".$value ."</a></td><td><a href=\"?path=mailrp&inbox=".$id&#91;$i&#93;."\">". $subject[$i]."</a> </td><td>" .$sendtime[$i]. " </td><td>".$suc[$i]."</td></tr>";
				$i++;
			}
			echo "</table>";

おお、メール機能の基本的なところは大分出来てきた!

次は、register時における性別、年齢などusersのカラムを増やして、メールボックスにfacebookのように、「知り合いかも?」で、異性のプロフィールを表示させてマッチングさせる機能を付けたいですね。

phpでメールボックスをつくろう8 メールのユニークIDをautoincrementからランダムな英数字にする

推測されないようにします。

$str = array_merge(range('a','z'), range('0', '9'), range('A', 'Z'));
	$r_str = null;
	for($i = 0; $i < 8; $i++){
		$r_str .= $str[rand(0, count($str) - 1)];
	}
	$mid = $r_str;

いいですね~!

続いて、send itemsで、メールが送信できたか否かを表示したいと思います。

添付ファイルの表示およびダウンロード

表示するphpファイル
写真が2枚の時は、vertical-align:topで上揃えにします。

<style>
#menu {
	border: solid 1px #f0f8ff;
	font-size:small;
	color:#d3d3d3;
	padding-left:10px;
}
#img{
	position: relative;
}
#img img{
	vertical-align:top;
}
</style>
<?php
$id = 15;

$dsn = "mysql:dbname=mail;host=localhost";
$user = "hoge";
$password = "hogehoge";
try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e){
    print('connection failed:'.$e->getMessage());
}
$sql = "select * from sends where id = '".$id."'";
$stmt = $dbh->query($sql);

$result = $stmt->fetch(PDO::FETCH_ASSOC);
$send_from = $result['username'];
$send_sub = $result['subject'];
$send_body = $result['body'];
$sendtime = $result['sendtime'];
$file1 = $result['file1'];
$file2 = $result['file2']; 

echo "<h3>".$send_sub."</h3>";
echo "From: ".$send_from. "<br>";
echo $sendtime. "<hr>";
echo $send_body. "<br>";
if(!empty($file2)){
	echo "<br><div id=\"img\"><img src=\"".$file1."\"> <img src=\"".$file2."\"></div><br>";
	echo "<a href=\"wa.php?id=".$file1."\">1.ダウンロード</a> <a href=\"wa.php?id=".$file2."\">2.ダウンロード</a><br>";
}elseif(!empty($file1)){
	echo "<br><img src=\"".$file1."\"><br>";
	echo "<a href=\"wa.php?id=".$file1."\">ダウンロード</a><br>";
}
?>
<br>
<div id="menu"> <a href="?compose=reply&inbox=<?php echo $id; ?>">返信する</a> | <a href="?path=todelete&inbox=<?php echo $id; ?>">削除</a> | <a href="?path=tojunk&inbox=<?php echo $id; ?>">ジャンク</a></div>

ダウンロード押下すると、wa.phpで生成した画像ファイルをダウンロードします。
拡張子に応じて、switch文で切り替えます。
wa.php (web access ※outlookの真似をしました)

<?php 

$fpath = $_GET&#91;'id'&#93;;
$ext = substr($fpath, strrpos($fpath, '.') + 1);

$date = date(Ymdhis);

switch ($ext) {
	case 'jpeg':
		$fname = "".$date.".jpeg";
		header('Content-Type: application/force-download');
		header('Content-Length: '.filesize($fpath));
		header('Content-disposition: attachment; filename="'.$fname.'"');
		readfile($fpath);
		break;
	case 'gif':
		$fname = "".$date.".gif";
		header('Content-Type: application/force-download');
		header('Content-Length: '.filesize($fpath));
		header('Content-disposition: attachment; filename="'.$fname.'"');
		readfile($fpath);
		break;
	case 'png':
		$fname = "".$date.".png";
		header('Content-Type: application/force-download');
		header('Content-Length: '.filesize($fpath));
		header('Content-disposition: attachment; filename="'.$fname.'"');
		readfile($fpath);
		break;
	default:
		$fname = "".$date.".jpg";
		header('Content-Type: application/force-download');
		header('Content-Length: '.filesize($fpath));
		header('Content-disposition: attachment; filename="'.$fname.'"');
		readfile($fpath);
		break;
}
?>

まーいいんじゃないでしょうか。

添付が1枚の時

つなげると、

OK! Good!

さて、idはauto incrementではなく、乱英数字8桁くらいにしたいですね。

$str = array_merge(range('a','z'), range('0', '9'), range('A', 'Z'));
$r_str = null;
for($i = 0; $i < 8; $i++){
	$r_str .= $str[rand(0, count($str) - 1)];
}
echo $r_str;

ほい

Gmail、hotmail、Yahoo!添付ファイル受信時の表示とURLの設計

gmail
-> 写真が表示されます。

hotmail
-> 写真を表示

yahoomail
-> 写真表示

ぬぬぬ、なるほど、基本は表示ですね。

ダウンロード時のURI
gmail:https://mail.google.com/mail/u/0/?ui=2&ik=10桁の英数字&view=att&th=16桁の英数字&attid=0.1&disp=safe&realattid=f_9桁の英数字&zw
hotmail:https://attachment.outlook.live.net/owa/hoge@hotmail.com/service.svc/s/GetAttachmentThumbnail?id=AQMkADAwATE2MjYxLTU3MmEtMGU4ZC0wMAItMDAKAEYAAAPamN5TZvIjQZibMQuFo… 以下略
yahoo: https://jp.mg5.mail.yahoo.co.jp/neo/launch?.rand=13桁の英数字#

なんじゃこりゃ?URIだけ見ると、yahooは比較的シンプルに見える。
hotmailは、subdomainがattachmentに変わって、id, x-owa-canary(意味不明?), tokenなどのパラメーターが色々ついています。※owaはoutlook web accessの略ですね。
これ、どういう設計になってるんでしょう???
もう、誰だよ、これつくってるの。

mysqlからデータを取り出して、form・textareaに挿入する

複数行のデータは、explode(“\n”, $hoge);で、1行ずつ配列に変換
inputはvalueに変数を代入、textareaはタグ内に挿入
textareaの改行は”&#13″を使う。

<?php
	$dsn = "mysql:dbname=mail;host=localhost";
	$user = "hoge";
	$password = "hogehoge";
	$id = 5;
	try {
	    $dbh = new PDO($dsn, $user, $password);
	} catch (PDOException $e){
	    print('connection failed:'.$e->getMessage());
	}
		$sql = "select * from sends where id = $id";
	$stmt = $dbh->query($sql);

	$result = $stmt->fetch(PDO::FETCH_ASSOC);
	$to = $result['username'];
	$subject = $result['subject'];
	$body = $result['body'];
	$body = explode("\n", $body);
	$sendtime = $result['sendtime'];
?>
<span id="fs-s">※必須</span><br>
<input type="text" name="to" size="90%" value="<?php echo $to ?>" required><br>
件名<br>
<input type="text" name="subject" value="><?php echo $subject; ?>" size="90%"><br>
本文
<span id="fs-s">※必須</span><br>
<textarea name="body" rows="12" cols="100%" required>
&#13;&#13;<?php
			echo ">".$sendtime ."&#13;"; 
		foreach($body as $value){
			echo ">" .$value;
		}
	?>
</textarea>
</p>
<input type="file" id="files" name="files&#91;&#93;" multiple />
<div id="caution">
※送信できるファイルの拡張子は"gif","jpg","jpeg","png"の何れかです。<br>
※ファイル送信は最大2つまでです。3つ以上選択しても、3つ目以降は送れません。また、二つのファイルを送信する場合は、キーボードの"ctl"ボタンなどで二つ選択した状態で開いてください。</div>
<output id="list"></output>
<p>
<input type="submit" value="送信">
</form>

返信っぽい表示になっていますね。

では、代入していきます。

メール詳細

返信押下

返信

送信済メール

割と簡単でしたね。

値がNULLのselect文

“columname is NULL”で選択できます。

select * from sends where destination = '".$username."' and deleted is NULL and junk is NULL order by sendtime desc

受信トレイ

メール本文

「削除」もしくは「ジャンク」がクリックされた場合は、pdoのupdateでテーブル側のステータスを変更します。

<div id="menu"> <a href="?path=todelete&inbox=<?php echo $id; ?>">削除</a> | <a href="?path=tojunk&inbox=<?php echo $id; ?>">ジャンク</a></div>

変更された対象のテーブルを読み込む。

$sql = "update sends set junk = :junk where id = ".$id.""

基本的なところは大分出来てきましたね♪

あと大きなところとして、1.メールの返信機能、2.添付ファイルの表示
余力があれば、3.Post後にPHP側で宛先の有り無しをチェックして、表示の出し分け

メールの返信はどうすればいいんでしょう?
機能としては、新規作成メールのformに、対象のレコードを呼び出して、fromをtoにセットして、返信するメールのsendtime, subject, bodyを新規メールのbodyの下部に返信とわかるように追加、というところでしょうか。
結構ややこしいですね。

phpでメールボックスをつくろう7 送信したメールを表示

getパラメーターでメールのidを取得して、テーブルから呼び出します。

<?php elseif($_GET&#91;"path"&#93; == 'mailrp'): ?>
			<?php
			$id = empty($_GET&#91;"inbox"&#93;)? 'null' : $_GET&#91;"inbox"&#93;;

			$dsn = "mysql:dbname=mail;host=localhost";
			$user = "hoge";
			$password = "hogehoge";
			try {
			    $dbh = new PDO($dsn, $user, $password);
			} catch (PDOException $e){
			    print('connection failed:'.$e->getMessage());
			}
			$sql3 = "select * from sends where id = '".$id."'";
			$stmt3 = $dbh->query($sql3);

			$result3 = $stmt3->fetch(PDO::FETCH_ASSOC);
			$send_des = $result3['destination'];
			$send_sub = $result3['subject'];
			$send_body = $result3['body'];
			$sendtime = $result3['sendtime'];

			echo "<h3>".$send_sub."</h3>";
			echo "To: ".$send_des. "<br>";
			echo $sendtime. "<hr>";
			echo $send_body. "<br>";
			?>
   <?php endif; ?>

1.nakayamaさんにメールを書く

2.送信する

3.送信一覧

4.メール詳細を表示

送信一覧は、order byでソート順逆ですね。

$sql2 = "select * from sends where username = '".$username."' order by sendtime desc";

新着順にしました。

添付ファイルの表示設計は面倒なので後にして、受信ボックスを先に作りたいと思います。

受信ボックス

受信メール

phpでメールボックスをつくろう6 送信メールの宛先・タイトルを表示

テーブルからデータを引っ張てきます。

<?php elseif($_GET&#91;"path"&#93; == 'sentitems'): ?>
   			<h2>Sent Items</h2>
   			<?php 
   			$dsn = "mysql:dbname=mail;host=localhost";
			$user = "hoge";
			$password = "hogehoge";
			$username = $_SESSION&#91;"username"&#93;;
			try {
			    $dbh2 = new PDO($dsn, $user, $password);
			} catch (PDOException $e){
			    print('connection failed:'.$e->getMessage());
			}
   			$sql2 = "select * from sends where username = '".$username."'";
			$stmt2 = $dbh2->query($sql2);

			while($result = $stmt2->fetch(PDO::FETCH_ASSOC)){
				$id[] = $result['id'];
				$destination[] = $result['destination'];
				$subject[] = $result['subject'];
				$sendtime[] = $result['sendtime'];
			}
			$i= 0;
			echo "<table>";
			foreach($destination as $value){
				echo "<tr><td> <img src=\"icon.png\"> <a href=\"\">".$value ."</a></td><td><a href=\"\">". $subject[$i]."</a> </td><td>" .$sendtime[$i]. " </td></tr>";
				$i++;
			}
			echo "</table>";
			?>
   <?php endif; ?>

アイコンをつけてそれっぽくします。

idで、メール詳細に移動するようにします。

あああ、なるほど、gmailはメール詳細に飛ぶ際に、乱数字16桁のid使ってますね。
なるほどな~!

ALTER TABLEでデータベースのカラムを成形

alter tableでメール送信、受信用テーブルのカラム追加、削除を行っていきます。

ALTER TABLE sends ADD alreadyread int afetr junk;

mysql> desc sends;
+————-+——————+——+—–+———+—————-+
| Field | Type | Null | Key | Default | Extra |
+————-+——————+——+—–+———+—————-+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| username | varchar(41) | YES | | NULL | |
| destination | varchar(41) | YES | | NULL | |
| subject | varchar(255) | YES | | NULL | |
| body | varchar(255) | YES | | NULL | |
| file1 | varchar(255) | YES | | NULL | |
| file2 | varchar(255) | YES | | NULL | |
| alreadyread | int(11) | YES | | NULL | |
| junk | int(11) | YES | | NULL | |
| deleted | int(11) | YES | | NULL | |
| sendtime | datetime | YES | | NULL | |
+————-+——————+——+—–+———+—————-+
11 rows in set (0.07 sec)

メールボックスをつくろう5 複数添付ファイルの保存パスをDBに格納

php側
画像保存後は、unlinkで一時フォルダの画像を削除します。

session_start();

if(!empty($_FILES['files']['name'])){
      $rand = mt_rand(1,9);
      $date = date("ymdHis");
      $path = "upload/img/".$date.$rand;
      mkdir($path, 0777);
    }

    for ($i=0; $i<count($_FILES&#91;'files'&#93;&#91;'name'&#93;) and $i < 2; $i++) {
    $file_ext = pathinfo($_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93;, PATHINFO_EXTENSION);
    if (FileExtensionGetAllowUpload($file_ext) &&  is_uploaded_file($_FILES&#91;"files"&#93;&#91;"tmp_name"&#93;&#91;$i&#93;)) {
      if(move_uploaded_file($_FILES&#91;"files"&#93;&#91;"tmp_name"&#93;&#91;$i&#93;, $path."/".$_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93;)) {
          $message .= $_FILES&#91;"files"&#93;&#91;"name"&#93;&#91;$i&#93; . "を送信しました。<br>";
          if($i == 0){
            $file1 = $path."/".$_FILES["files"]["name"][$i];
            $message .= "file1のパスは ".$file1." です。<br>";
          } else {
            $file2 = $path."/".$_FILES["files"]["name"][$i];
            $message .= "file2のパスは ".$file2." です。<br>";
          }
      } else {
        $message = "ファイルをアップロードできません。<br>";
      }
    } else {
      $message = "ファイルが選択されていません。<br>";
    }
  }
  function FileExtensionGetAllowUpload($ext){
    $allow_ext = array("gif","jpg","jpeg","png");
    foreach($allow_ext as $v){
      if ($v === $ext){
        return 1;
      }
    }
    return 0;
  }
unlink($_FILES['files']['name']);

if(isset($_POST["to"])){
	$username = $_SESSION["username"];
	$destination = htmlspecialchars($_POST["to"]);
	$subject = htmlspecialchars($_POST["subject"]);
	$body = htmlspecialchars($_POST["body"]);
	$date =	date("Y-m-d H:i");

	$dsn = "mysql:dbname=mail;host=localhost";
	$user = "hoge";
	$password = "hogehogehoge";
	 
	try {
	    $dbh = new PDO($dsn, $user, $password);
	} catch (PDOException $e){
	    print('connection failed:'.$e->getMessage());
	}

	$stmt = $dbh -> prepare("INSERT INTO sends (username, destination, subject, body, file1, file2, sendtime) VALUES(:username, :destination, :subject, :body, :file1, :file2, :sendtime)");
    $stmt->bindParam(':username', $username, PDO::PARAM_STR);
    $stmt->bindParam(':destination', $destination, PDO::PARAM_STR);
    $stmt->bindParam(':subject', $subject, PDO::PARAM_STR);
    $stmt->bindParam(':body', $body, PDO::PARAM_STR);
    $stmt->bindParam(':file1', $file1, PDO::PARAM_STR);
    $stmt->bindParam(':file2', $file2, PDO::PARAM_STR);
    $stmt->bindParam(':sendtime', $date, PDO::PARAM_STR);
    $stmt->execute();
}

ブラウザ(画像添付時)

画像フォルダ

mysql sendsテーブル
おおお、入ってる! いいね♪

新規送信機能はほぼ出来たので、次はテーブル情報の呼び出しですね。
二重にDBに登録する理由はないので、メール受信者もsendsテーブルの呼び出しでつくってみたいと思います。

パラメータがsentitemsの時に表示