メール配信の最近のブログ記事

久々にメールアドレスでも新しく作ろうと思って、nologinで新規ユーザ作成してみた。

thunderbirdでちゃちゃちゃとアカウント設定して、いざ受信って思ったら、
「接続:ホストにログイン情報を送信しています・・・」
のまま音沙汰なし。

パスワードとかいろいろ確認しても特におかしくないので、とりあえずmaillogを確認したら、こんなメッセージが。

-----------------------------------------------------------------------------------------
dovecot.... mail_location not set and autodetection failed: Mail storage autodetection failed with home=......
-----------------------------------------------------------------------------------------

うーん、これはなんだろう。

なんか雰囲気的に、メールボックスの場所が指定されてないから、メールを取りにいけません的な感じだろうか・・・

おかしいなあ、前までは普通にユーザ作成してメーラーの設定するだけですぐにいけたんだけどなあ・・・
と思いつつ、とりあえず問題ありそうな「/etc/dovecot.conf」を確認。

ってゆうか、このファイル一回も中身見たことないし〜。

メールサーバ入れたときもdovecotの設定なんか一回もやんなかったのに・・・
デフォルトでいままでいけてたんですけどね。


でもなんかこの辺が臭かったので、

-------------------------------------------------------------------------------------------
# Location for users' mailboxes. This is the same as the old default_mail_env
# setting. The default is empty, which means that Dovecot tries to find the
# mailboxes automatically. This won't work if the user doesn't have any mail
# yet, so you should explicitly tell Dovecot the full location.
#
# If you're using mbox, giving a path to the INBOX file (eg. /var/mail/%u)
# isn't enough. You'll also need to tell Dovecot where the other mailboxes are
# kept. This is called the "root mail directory", and it must be the first
# path given in the mail_location setting.
#
# There are a few special variables you can use, eg.:
#
# %u - username
# %n - user part in user@domain, same as %u if there's no domain
# %d - domain part in user@domain, empty if there's no domain
# %h - home directory
#
# See for full list. Some examples:
#
# mail_location = maildir:~/Maildir
# mail_location = mbox:~/mail:INBOX=/var/mail/%u
# mail_location = mbox:/var/mail/%d/%1n/%n:INDEX=/var/indexes/%d/%1n/%n
#
#
#
#mail_location =
-------------------------------------------------------------------------------------------

google様で直訳してみると、locationの設定は必須ですよ〜みたいな感じなのかな?

とりあえず例のまんま設定してみる。

-------------------------------------------------------------------------------------------
mail_location = mbox:~/mail:INBOX=/var/mail/%u
-------------------------------------------------------------------------------------------

てなかんじ。

すると・・・おお!メーラーがちゃんとメールを読みに行った!

なんじゃそりゃ。


ユーザディレクトリにも「mail」ディレクトリが作成されてる。
さっきまで無かったのに・・・
この「mail」ディレクトリって何なのかわかんなかったけど、dovecotが勝手に作ってるんですね・・・


とりあえずpopはOKそうなので、ついでにSMTP(postfix)の方も確認。
/etc/postfix/main.cfを開いて、それっぽい部分を見てみると、

-------------------------------------------------------------------------------------------
# DELIVERY TO MAILBOX
#
# The home_mailbox parameter specifies the optional pathname of a
# mailbox file relative to a user's home directory. The default
# mailbox file is /var/spool/mail/user or /var/mail/user. Specify
# "Maildir/" for qmail-style delivery (the / is required).
#
#home_mailbox = Mailbox
#home_mailbox = Maildir/
-------------------------------------------------------------------------------------------

どうやら、デフォルトのメールボックスは/var/spool/mail/userか、 /var/mail/userで、何もいじらないとここにメールを届けに行くらしい。
というわけで、さっきのdovecotの設定とつじつまがあってるのでOK。

まあ、ちゃんとした人たちはMaildir形式にちゃんと設定してるんだろうけど、横着な私はこれで問題無し。


一応確認のためにpostfixから送信して、dovecotで取りに行ってちゃんと読めたのでめでたし。

しかし軽く7時間かかったのは痛かった。


サーバ立ち上げた時から今まで問題なかったのに、いつからdovecotのデフォルト設定変わったの?って感じ。

アップデートなんてまったくやってないのに。

・・・よくわからないなー
とりあえずサンプルスクリプト↓

-----------------------------------------------------------------------

use strict;
use CGI::Carp qw(fatalsToBrowser);
use Net::SMTP;
use Net::SMTP::SSL;
use Net::SMTP::TLS;
use Encode qw(from_to encode);

#メールアドレス設定
my $from = 'hoge@gmail.com';
my $mailto= 'huga@nantoka.com';

#件名設定
my $subject = 'SMTPを指定してメール送信!';
from_to($subject, 'shiftjis', 'iso-2022-jp');
encode('MIME-Header-ISO_2022_JP', $subject);

#メールヘッダー設定
my $header = << "MAILHEADER";
From: $from
To: $mailto
Subject: $subject
Mime-Version: 1.0
Content-Type: text/plain; charset = 'ISO-2022-JP"
Content-Trensfer-Encoding: 7bit

MAILHEADER

#メール本文設定
my $message = << 'MAILBODY';
本日は晴天なり。

あああいいいううう
さよーなら!
MAILBODY

#文字コードをJISに変換
from_to($message, 'shiftjis', 'iso-2022-jp');

#SMTP設定(適宜変更してください)
my $server = 'smtp.gmail.com'; #ホスト名
my $auth = 1; #SMTPAuthを使用する場合は1
my $tls = 0; #TLS接続を使う場合は1
my $ssl = 1; #SSL接続を使う場合は1
my $port = 465; #ポート指定。指定しないと25番が勝手に設定される
my $user = 'hoge@gmail.com'; #SMTPAuthのユーザ名
my $pass = 'passwaord'; #SMTPAuthのパスワード

#メール送信オブジェクト設定
my $smtp = '';

#TLSのときは、オブジェクト生成時にAuthデータを渡す
if($tls){
 $smtp = Net::SMTP::TLS->new(
  $server,
  Port => $port ,
  User => $user ,
  Password => $pass
 ) || die "Connect failed over tls";
}
elsif($ssl){
 $smtp = Net::SMTP::SSL->new(
  $server,
  Port => $port
 ) || die "Connect failed over ssl";
}
else{
 $smtp = Net::SMTP->new($server, Port => $port) || die "Connect failed";
}
if(!$tls && $auth){
 $smtp->auth($user, $pass) || die "auth failed";
}

#メール送信
$smtp->mail($from);
$smtp->to($mailto);
$smtp->data();
$smtp->datasend($header);
$smtp->datasend($message);
$smtp->dataend();
$smtp->quit;

print <<EOM;
Content-type: text/html

送信しました~!
EOM

exit;
1;

---------------------------------------------------------------------------------

※Net::SMTP::SSLおよびNet::SMTP::TLSを使うには、IO::Socket::SSLモジュールが必要。
※IO::Socket::SSLをインストールするには、Net::SSLeayモジュールが必要
※試したところ、gmailの場合は、TLS使用&ポート587でも送信できた。
※例ではエンコードにEncodeモジュールを使っているが、Jcodeとか使いたい人はお好きなように。
前回、postfixのaliasを設定して、rootレベルで自動処理する方法を書いた。

http://www.igreks.jp/dev/2008/11/postfix2.html
http://www.igreks.jp/dev/2008/11/post.html

しかし、この方法はpostfixのconfigファイルを書き換えたり、エイリアス設定をしたりしなくてはならないので、root権限を持たないレンタルサーバの1ユーザレベルでは、かなり敷居が高い。

というわけで、少し自動処理の正確性は落ちるけれども、もっと簡単な方法を紹介。

おそらく「N●O」とかはこのやり方じゃないかと思われる。
「N●O」はPHPみたいだけど、私はPHPあまり得意じゃないのでPerlで。


[動作条件]
・perl5以上(確認した環境はは5.10)かつMail::POP3Clientモジュールがインストールされていること。
・POPアクセスにSSLを用いる場合(Gmailなど)は、さらにIO::Socket::SSLモジュール(要コンパイラ)が必要。
・あらかじめエラーメール受信専用のアドレスを作っておいて、メール送信する時にエンペロープFROMをそのアドレスに指定しておく。
・CRONなどで以下のスクリプトを実行する。
-------------------------------------------------------------------
#/usr/bin/perl -w
use strict;
use Mail::POP3Client;

my $log = "POPサーバに接続中・・・\n";

#コンストラクタ 
my $pop = new Mail::POP3Client(
  USER => 'pop_user', #popサーバのユーザ名
  PASSWORD => 'pop_pwd', #同パスワード
  HOST => 'pop.gmail.com', #popサーバ名
  AUTH_MODE => 'BEST', #認証モード(たいていはBESTでOK)
  DEBUG => 0, #デバッグ有無(正の整数を指定すると、プロンプトにサーバとのやりとりが表示される)
  TIMEOUT => 10, #接続タイムアウト秒(デフォルトは60)
  USESSL => 'true' #SSLを使わない場合は0(Gmailは使う)
 );


if($pop->Count < 0){ #接続に失敗すると-1が返るらしい
 $log .= "POPサーバに接続できませんでした";
}
else{
 $log .= "ID[$id]のエラーメールアドレスを調査中・・・\n";
  if($pop->Count != 0){
   my @err = ();
   my $suc = 0;
   $log .= $pop->Count."件のエラーメールアドレスを処理中・・・\n";

   #サーバにある数だけ読み込む
   for(my $i=1; $i <= $pop->Count; $i++){

    #本文を1行ずつ取得
    foreach($pop->Body($i)){

    #予めbase64エンコードしておいて「名前<メールアドレス>」の形にしておくとToヘッダのパースが楽ちん。
    if($_ =~ /To:\s=\?iso-2022-jp\?B\?.+?\?=<(.+\@.+(\..+)+)>/i){
     push(@err,$1);
     $suc++;

     #パースに成功したらサーバのメッセージ削除フラグを立てる
     $pop->Delete($i);
     last;
    }
   }
  }
  if(@err){

   ####ここらでエラーアドレスをDBから削除する処理など
   foreach(@err){
    &db::query("DELETE FROM usertable WHERE email='$_'");
   }
   $log .= "$suc件のエラーメールアドレスをデータベースから削除しました\n";
  }

  #相手先MTAによっては、パースに失敗することもあるでしょう。
  if($pop->Count - $suc > 0){
   $log .= "※".$pop->Count - $suc."件のエラーメールアドレスを削除できませんでした\n";
  }
 }
 else{
  $log .= "エラーメールアドレスはありませんでした\n";
 }
}

#接続終了(このときメールがサーバから削除される)
$pop->Close;

print $log;

------------------------------------------------------------------------

※Mail::POP3ClientモジュールはPurePerlなのでなければCPANからダウンロードして、同じフォルダに置けば使える。
※IO::Socket::SSLが使えなければ、POPサーバをYahooとかの110番を使えばOK。
※SSL未対応でもよければNet::POP3モジュールとか使ってもOK。
メルマガ配信した累計秒数を管理画面で参照したりするのに、秒数をhh:mm:ss形式に
したいなーということで・・・

例えば、

10  → 00:00:10
60  → 00:01:00
3601  → 01:00:01

みたいな感じ。

これをスクリプト側で操作するとなると、累計秒をローカルタイム形式に直して
sprintfとかで整形してだらだらだら・・・

と、意外とけっこう面倒くさかったり無駄なメモリを消費したり、なんか効率悪い。
てゆーか、こういう処理はなるべく書きたくないし。

そう思って、ググってたら、目的を一発で達成できるなんとも便利なSQL文を
発見。

------------------------------------------------------------------

「SEC_TO_TIME( 秒数 )」

------------------------------------------------------------------

これで、秒数を勝手にhh:mm:ss形式に変換してくれる。


SELECT SEC_TO_TIME(秒数)

で変換&参照できるが、DBから参照するんであれば、最初から
データ型をTIMEにしておき、

※$timeには秒数を格納

INSERT INTO table VALUES('SEC_TO_TOME($time)')

とかで、あらかじめhh:mm:ss形式でデータをぶち込んでおいてやれば、
インタフェイスが変わったときも便利。


あらためて、データベースって素晴らしいと思った次第。


ちなみにこれの逆は、

TIME_TO_SEC( hh:mm:ss )で、

TIME_TO_SEC(01:00:01) は、 3601 となる。
こういった場合、今まで

-------------------------------------------------
##直後に"mogemoge"含まない文字列にマッチ

$str =~ /hogehoge[^(mogemoge)]/;

-------------------------------------------------

これでいけたような気がしたんだが、久々に同じような処理を書いてみたら
これではダメだった。

前回はなんでうまくいったのか分からないが、クラスのマッチはやはり
一文字分しか指定できないらしいので、セオリーどおり、否定先読みを使う。


-------------------------------------------------
##直後に"mogemoge"含まない文字列にマッチ

$str =~ /hogehoge(?!mogemoge)/;



##"mogemoge"の部分はさらに正規表現を使ったり、変数を使ったりもできる

my $later = "moge";

$str1 = "hogehoge";
$str2 = "hogehogemogemoge";

$str1 =~ s/hogehoge(?!($later){1,})/oeoe/;
$str2 =~ s/hogehoge(?!($later){1,})/oeoe/;

print $str1."
".$str2;


結果:
hogehogeoeoe
hogehogemogemoge
-------------------------------------------------

逆に、特定の文字列を後方に含む場合は

(?!mogemoge) を (?=mogemoge)

にかればいいだけ。
大量のメルマガなどを配信する場合、サーバのスペックによってMTAにキューを投げる
間隔(時間)を調整したり、他サーバをリレーさせたりするのが一般的。

ただこれらをブラウザから行なうと、いつまでもブラウザが開放されず、timeoutに
なってしまう。
なのでこういった場合は、時間のかかる処理をバックグラウンドにまわして、ブラウザは
さっさと開放する。
(「まぐ●ぐ!」などで、即時配信した後、すぐ管理画面に戻れるのはそういった
仕掛けがあるからです。)

perlでバックグラウンド実行を行なうには、fork()関数か、ithreadを使う場合が多い
らしい。

速さから言えばithreadのほうが速いらしいが、ithreadは必要なモジュールが標準でセットされてないので、お手軽なのはfork()。←現在は標準になってる模様

-------------------------------------------------------------------
#!/usr/bin/perl -w

$| = 1; #バッファ制御

sub start_imme{ #### 即時配信処理

######## ここらでパラメータ受け取り

########## ここらでメールデータをセット

########### ここらでMIMEフォーマットなど

########## ここらで配信する読者をセット

my @user_no = "配信するユーザ番号など";

if(@user_no == 0){
&error("配信可能な読者がいませんでした。");
}
######## ここからバックグラウンド処理開始
else{
FORKLABEL: { ##ラベル開始
if( $pid = fork ) { # 子プロセス生成。$pidにはforkのプロセスNoが返る
###### ここは親プロセスのみで実行
&show_imme_done(); ###「配信完了」などの表示をここで出力
###### 標準出力を閉じてブラウザ開放
close(STDOUT);
wait;  ###### 子プロセスを待たないと子がゾンビになります
}elsif (defined $pid) {
###### ここは子プロセスのみで実行

###### 標準出力を閉じてブラウザ開放
close(STDOUT);

###### ここらから時間のかかる処理

######### メール送信
my $mass = 10; # 一斉送信数
my $interval = 5; # 待ち時間
my $i = 0;
my $bench = time;
while($i < @user_no){
&sendmail(
$mail_to,
$mail_from,
$reply_add,
$envelope_add,
$sbj,
$body
);
if($i){
if($i % $mass == 0){
sleep $interval;
}
}
$i++;
}
my $req_time = time - $bench;

########## この辺で配信履歴の保存処理など

}elsif ( $! =~ /No more process/) {
# 生成するプロセスが多すぎる時は、少し待って再チャレンジ。
sleep 10;
redo FORKLABEL;
}else {
##### ここにくるようなら、perl自体動かないはず。

die "forkがサポートされていません。サーバ管理者にお問い合わせください。";
}
} # ラベルの閉じ
}
exit;
}
同じサーバでメインのドメイン以下サブドメインを複数運用しているが、そのうちの一つでメールが送れない現象が発生。

最近BINDの設定をちゃちゃっと済ませていたので、メールログの内容をもよく見ないで、BINDの設定を間違ってると勝手に思い込んでいた。

zone設定ファイルと延々とにらめっこするも、決定的な原因見つからず・・・

$ nslookup -type=MX xxxx.jp

のコマンドは正常にMXが引けているし、named.confの設定も何回も見直したがどこもおかしくない。
ってゆうか、他のサブドメインと設定は一緒で、それらは問題なくメールの送受信ができてるのになぜ?みたいな感じになって頭を抱えていたら、maillogに
「・・・loops back to myself・・・」
というエラー文を発見。(遅っ!)

よくみたらバウンスメールにも書いてあるし・・・


・・・ということは、postfixのせいか?

ということでpostfixのmain,cfファイルをみてみたら、なんと

mydestination = の項目に、当該ドメインを指定し忘れている!!

やっちまったー、正味5時間の無駄。
指定した後は何ら問題なく送受信ができるようになりました。


というわけで、今日は、先入観を持たずに、常にmaillogを見るくせをつけようという教訓を得ました・・・

1.全てのcronからroot宛のメールを停止する場合。

「/etc/crontab」を開き、

MAILTO = root
   ↓
MAILTO = ""

に変更。


2.ジョブごとにメールを止めたいとき

cron設定ファイルやcrontabでコマンドを書くとき、

例1)
05 2 * * * root コマンド > /dev/null 2>&1 または、
05 2 * * * root コマンド > /dev/null 2> /dev/null
   ↓
メールを送らずログも残さない


例2)
05 2 * * * root コマンド 1> /dev/null
   ↓
標準出力は無視し、標準エラー出力をメールする。
(コマンド実行時にエラーがあったときだけメールする)


例3)
05 2 * * * root (コマンド > ログファイルのパス 2>&1) > /dev/null
   ↓
指定のログファイルにログを残すが、メールは送らない。



補足)
cron実行するスクリプトの文法チェックを行なうように設定しているが、いちいちどうでもいいようなチェックメッセージが毎回メールされてうっとうしい。
でも一応ログは残しておいて、後で参照したい。
・・・なんていう場合は「例3)」が個人的におすすめ。

MySQL(4.1.1以降)にて、2つのDATE型の値の差を求めるクエリ。
(※'2009-1-1'と'2009-1-8'であれば日数差は7。)

  2009-1-1から7日以上経過したレコードを返す場合。
-------------------------------------------------------------------------------------------------------
#$current = 本日の日付のDATE型

SELECT * FROM sample_table WHERE DATEDIFF('$crrent', '2009-1-1') >= 7

もしくは、

SELECT * FROM sample_table WHERE DATEDIFF('CURRENT_DATE()', '2009-1-1') >= 7
-------------------------------------------------------------------------------------------------------



 上記にhh:mm:ssを追加した場合
-------------------------------------------------------------------------------------------------------

SELECT * FROM sample_table WHERE DATEDIFF('$crrent 00:00:00', '2009-1-1 23:59:59') >= 7

または、

SELECT * FROM sample_table WHERE DATEDIFF('CURRENT_DATE() CURRENT_TIME()', '2009-1-1 23:59:59') >= 7

※結果は最初と同じ
-------------------------------------------------------------------------------------------------------




ステップメールの配信などに応用できる。

例)
user_table
+−−−−+−−−−−−−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−+
| ID  | MAIL        |  entry   | next_story |
+−−−−+−−−−−−−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−+
| 01  | hogehoge@hoge.jp |  2009-1-1 | 2     |
+−−−−+−−−−−−−−−−−−−−−−−−+−−−−−−−−−−+−−−−−−−−−−−+
     ・
     ・
     ・

登録日から指定日数経過した読者のレコードを求める例

SELECT * FROM user_table WHERE DATEDIFF('$current', entry) >= $day_interval and next_story=$tmp2 ORDER BY entry




その他日付関係操作の詳しい解説はこちら
http://www.limy.org/program/db/mysql/mysql_operators.html



無料のブログサービスだと、Seesaaとかlivedoorブログとか、携帯電話からの
メールをそのままブログ記事に反映させる機能をサポートしているものもあるが、
MTだと初期状態のままではこの機能は使えない。

そこでおすすめするのが、スカイアークシステムさんが開発した、MTプラグインの
一つである「MailPack」。
詳しくはこちら→ http://www.skyarc.co.jp/engineerblog/entry/4022.html

MTの個人無償ライセンス利用者に限り、こちらも無償でダウンロードできる。
(バージョンは1.1に限る)
また、プロ用で「MailPackPro」というのもあるらしいが、こちらは有償。
ただproじゃなくても、個人レベルでモブログする程度であれば、全く問題ないし、
Seesaaとかにも負けないくらい多機能なので、よっぽどのことがなければこれで
十分事足りると思う。


このプラグインを使うには以下のperlモジュールが必要なので、予めインストール
しておく。

・Net::POP3
・File::Basename
・File::Spec
・MIME-tools

SSLを利用する場合はさらに下記が必要。

・Mail::POP3Client
・IO::Socket::SSL

FCとかだと、yumから直接おとせるものもあるが、CPANに行けば全て揃っているので、
コマンド叩くのが面倒なら、全てブラウザからダウンロードしてmakeinstallした
ほうが早いかもしれない。


ちなみにCPAN用RPMのインストールの仕方と、perlモジュールインストール方法は以下。

コマンドラインからroot権限にて、
# yum -y install perl-ExtUtils-MakeMaker (cpan2rpmに必要なExtUtils::MakeMakerインストール)
   ↓
# yum -y install cpan2rpm (cpan2rpmインストール)
   ↓
※fedora10の場合
# yum -y install rpmdevtools ; rpmdev-setuptree (rpmbuildディレクトリ作成)
   ↓
何かperlモジュールをインストールしたい場合、
# cpan2rpm --no-sign --install File::Spec(File::Specパッケージをインストールする場合)


モジュールの準備ができたら、冒頭のURLからMailPack本体をダウンロード・解凍し、
MTのpluginsディレクトリ内に設置し、さらにmailpack.cgiの実行権限を755に変更。


次に、投稿専用のメールアカウントを作成しておく。
これは、GmailでもYahooメールでも、POP接続できるメールボックスであれば
何でも構わない。
自営サーバの場合は、ユーザを追加しておくだけで大抵のLinuxディストリビューション
なら勝手にメールボックスが作られるはず。

このプラグインは、指定時間になるとこの指定された受信メールBOXにPOPで
接続して、メールBOXからメールを削除しメール内容を記事としてMTに投稿する。

なので、投稿専用にしておかないと、投稿したくもない受信メールが勝手に記事として
投稿されてしまうので注意。


次に管理者権限でエディタを立ち上げ、/etc/cron.d/ 内に新規ファイルを作成し、

*/10 * * * * root cd (MTのメインディレクトリのパス); ./tools/run-periodic-tasks

と記述し「mt-task」とか適当に名前付けて保存。
(この場合は、10分おきにタスク起動→メール送信から早くて10分後にブログ記事に反映。)


その後MTにログインすると、DBのアップデートを尋ねられるので、「OK」。
   ↓
ログイン後、システムメニューに「メール投稿設定」という項目が追加されている。

「投稿先メールアドレスの追加」から各種設定を行なう。

ごっちゃになりやすいが、
「投稿先のメールアドレスを入力してください」の欄には、先ほど作った
投稿専用のメールアドレスを入力。
「メールアドレスのユーザ名を入力してください」の欄には、たいてい前者と同じか、@から前の部分を入力する。
(要は、メールソフトの設定でいうところの、POPサーバ接続ユーザ名)


続いて、「新規作成」→「ユーザ」で、メール投稿専用のユーザを作成。
(既存のユーザの設定を変更して行なうことも出きるが、おすすめしない。)

名前などは適当に決めてよいが、「電子メール」の項目は、「メールを送信する
送信元のメールアドレス」を設定する。
(携帯から送るのであれば、その携帯のメールアドレス)
※このプラグインは、送信元メールアドレスを見て、記事の投稿を行なえる
権限を持つユーザかどうかを判断している。


最後に、追加したユーザに「権限」の設定から、ユーザまたはライターなどの
権限を付与すれば設定完了。



試しに先ほど作成した投稿専用のメールアドレス宛に、メールを送ってみよう。

10分後に指定したブログに、メールの内容が記事として投稿されていれば成功だ。

うまくいかない場合は以下の理由が考えられる。

・メールの送信元アドレスがMTのユーザの電子メールと違う。
・MTのユーザに記事を投稿する権限がない。
・投稿専用アドレスのPOP接続ユーザ名・パスワードが間違っている。
・cronの設定が間違っている。
・cronデーモンが起動していない。
など。

MTシステムメニューの「ツール」→「ログ」を参照すれば大抵の原因は
わかるはず。

このアーカイブについて

このページには、過去に書かれたブログ記事のうちメール配信カテゴリに属しているものが含まれています。

前のカテゴリはブログです。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

Powered by Movable Type 4.22-ja