JAVA MAILを使用して、IMAP POP3からメールを取得するクラスです
ここ2年ばかりPHPをやってきたのだけど、JAVAがやっぱりいいということで、JAVAをやるはめになりました。
ブログのタイトルは「PHP開発」ですが、昔に戻って、当分JAVAをやりそうです。
よろしく!
そんなことで、Java Mailを使ってメールボックスからメールを取得するクラスを作ってみました。
ご意見ご感想をお待ちしています。
package jp.compsys.common.util;
import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Address;
import javax.mail.Message.RecipientType;
import javax.mail.internet.MimeUtility;
import com.sun.mail.util.QPDecoderStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Comparator;
import java.util.Properties;
import java.util.ArrayList;
/**
* サーバからメールを取得するクラス.
*
* @author Computer System Corp tamura
* @since 1.6
* @version 1.0
* @since 1.0
*/
public class MailReader implements Serializable
{
private static final long serialVersionUID = -8161055025994457665L;
private String server;
private String protocol = "imap";
private int port = 143;
private String userId;
private String password;
private int pageNo = 0;
private int recordCount = 0;
private int maxPageNo = 0;
private Session session;
private Store store;
private Folder folder;
/**
* MailReaderのコンストラクタ.
* @param server 接続するサーバ名またはIPアドレス
* @param port 接続するポート番号
* @param userId 接続するユーザID
* @param password 接続するパスワード
* @since 1.6
*/
public MailReader(String server, int port, String userId, String password)
{
this.server = server;
this.protocol="imap";
this.port = port;
this.userId = userId;
this.password = password;
/*
this.protocol="pop3";
this.port = -1;
*/
}
/**
* メールの内容を取得する。.
* @param msgnum メッセージ番号
* @return MailItemのインスタンスを返す。取得できない場合はnullを返す。
*/
public MailItem getMail(int msgnum)
{
MailItem mailItem = new MailItem();
if(!open()) return null;
try
{
folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
if (!folder.exists())
{
close();
return null;
}
Message m = folder.getMessage(msgnum);
messageEdit(m, mailItem);
Part p = m;
partSet(p, mailItem);
} catch (MessagingException ex)
{
mailItem = null;
ex.printStackTrace();
} catch (IOException ex)
{
mailItem = null;
ex.printStackTrace();
}
close();
return mailItem;
}
/**
* メールの一覧を取得(mailList)した後の実際の取得ページ番号を取得する。
* mailListメソッドを実行した後でなければ正しい値を返さない。.
*/
public int getPageNo()
{
return pageNo;
}
/**
* メールの一覧を取得(mailList)した時の総メール数を取得する。
* mailListメソッドを実行した後でなければ正しい値を返さない.
*/
public int getRecordCount()
{
return recordCount;
}
/**
* メールの一覧を取得(mailList)した時の最大ページ数を取得する。
* mailListメソッドを実行した後でなければ正しい値を返さない.
*/
public int getMaxPageNo()
{
return maxPageNo;
}
/**
* メールサーバに接続する。.
* @return true:成功 false:失敗
*/
private boolean open()
{
Properties properties = System.getProperties();
session = Session.getInstance(properties, null);
try
{
store = session.getStore(protocol);
store.connect(server, port, userId, password);
return true;
} catch (MessagingException ex)
{
ex.printStackTrace();
return false;
}
}
/**
* メールサーバとの接続をクローズする
*/
private void close()
{
if (null != store)
{
try
{
store.close();
} catch (MessagingException ex)
{
}
}
}
/**
* メールに含まれるメッセージや添付ファイルを取得する。.
*/
@SuppressWarnings("unchecked")
public void partSet(Part p, MailItem m) throws MessagingException, IOException
{
MailContent mailContent = new MailContent();
String disp = p.getDisposition();
if (p.isMimeType("multipart/*"))
{ // マルチパートの場合
Multipart mp = (Multipart) p.getContent();
int count = mp.getCount();
for (int i = 0; i < count; i++)
{
partSet(mp.getBodyPart(i), m);
}
return;
}
else if (p.isMimeType("message/rfc822"))
{ // メッセージの場合
partSet((Part) p.getContent(), m);
return;
}
else if (p.isMimeType("text/*"))
{
if(disp != null && disp.equalsIgnoreCase(Part.ATTACHMENT))
{
mailContent.attachmentFlg = true;
}
mailContent.header = p.getAllHeaders();
mailContent.contentType = p.getContentType();
mailContent.content = content2string(p.getContent());
m.mailContents.add(mailContent);
return;
}
// 添付ファイルの場合
if (disp == null || disp.equalsIgnoreCase(Part.ATTACHMENT))
{
mailContent.contentBinaryFlg = true;
mailContent.fileName = p.getFileName();
if (mailContent.fileName != null)
{
mailContent.fileName = MimeUtility.decodeText(mailContent.fileName);
}
else
{
mailContent.fileName = "";
}
ByteArrayOutputStream os = new ByteArrayOutputStream();
try
{
p.writeTo(os);
mailContent.content_binary = os.toByteArray();
} catch (IOException e)
{
e.printStackTrace();
}
mailContent.header = p.getAllHeaders();
mailContent.contentType = p.getContentType();
mailContent.attachmentFlg=true;
m.mailContents.add(mailContent);
}
}
/**
* text/* に含まれるコンテンツを文字列として受け取る.
* @param textコンテンツの内容
*/
private String content2string(Object obj) throws MessagingException
{
String ret = "";
if (obj instanceof String)
{
return (String) obj;
}
else if (obj instanceof QPDecoderStream)
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
QPDecoderStream qps = (QPDecoderStream) obj;
while (true)
{
try
{
int c = qps.read();
if (c == -1) break;
os.write(c);
} catch (IOException ex)
{
return ret;
}
}
ret = os.toString();
}
else
{
throw new MessagingException("textのコンテンツファイルに未定義のものがあります");
}
return ret;
}
/**
* メールの一覧をぺジ単位に取得します。
* @param lineCount 1ページあたりの行数
* @param pageNo 取得したいページ
* @return 取得したメールの一覧を返します。メールがない場合はnullを返します。
*/
public ArrayList mailList(int lineCount, int pageNo)
{
this.pageNo = pageNo;
recordCount = 0;
maxPageNo = 0;
ArrayList list = null;
open();
int start = 0;
int end = 0;
int cnt = 0;
try
{
folder = store.getFolder("INBOX");
if (!folder.exists())
{
close();
return list;
}
folder.open(Folder.READ_ONLY);
cnt = folder.getMessageCount();
if (0 == cnt)
{
close();
return list;
}
recordCount = cnt;
maxPageNo = (int) Math.ceil((double) cnt / (double) lineCount);
if (this.pageNo maxPageNo) this.pageNo = maxPageNo;
list = new ArrayList(cnt);
Message mes[] = folder.getMessages();
for (Message m : mes)
{
MailItem mailItem = new MailItem();
messageEdit(m, mailItem);
// 一覧にメールの内容も取得したい場合はコメントをはずす かなり遅くなるのでやめたほうがいいです。
/* Part p = m;
partSet(p, mailItem);
*/ list.add(mailItem);
}
folder.close(false);
} catch (MessagingException ex)
{
ex.printStackTrace();
} catch (Exception e)
{
e.printStackTrace();
} finally
{
}
close();
Collections.sort(list, new Comparator()
{
public int compare(MailItem o1, MailItem o2)
{
return (o1.sentDate.compareTo(o2.sentDate) * (-1));
}
});
start = (this.pageNo - 1) * lineCount;
if (this.pageNo == maxPageNo)
{
end = start + ((cnt - 1) % lineCount);
}
else
{
end = start + lineCount - 1;
}
int i = -1;
ArrayList retList = new ArrayList(end - start + 1);
for (MailItem m : list)
{
i++;
if (i end) break;
retList.add(m);
}
return retList;
}
/**
* メッセージに含まれるヘダー情報を取得編集する。
* @param m javax.mail.Message
* @param mailItem 編集対象
*/
private void messageEdit(Message m, MailItem mailItem)
{
try
{
mailItem.messageNo = m.getMessageNumber();
mailItem.sentDate = m.getSentDate();
mailItem.receivedDate = m.getReceivedDate();
mailItem.subject = m.getSubject();
Flags flags = m.getFlags();
String[] userFlg = flags.getUserFlags();
{
if (m.isSet(Flags.Flag.ANSWERED))
{
mailItem.systemFlg.add("ANSWERED");
}
if (m.isSet(Flags.Flag.DELETED))
{
mailItem.systemFlg.add("DELETED");
}
if (m.isSet(Flags.Flag.DRAFT))
{
mailItem.systemFlg.add("DRAFT");
}
if (m.isSet(Flags.Flag.FLAGGED))
{
mailItem.systemFlg.add("FLAGGED");
}
if (m.isSet(Flags.Flag.RECENT))
{
mailItem.systemFlg.add("RECENT");
}
if (m.isSet(Flags.Flag.SEEN))
{
mailItem.systemFlg.add("SEEN");
}
if (m.isSet(Flags.Flag.USER))
{
mailItem.systemFlg.add("USER");
}
}
if (null != userFlg)
{
for (int i = 0; i < userFlg.length; i++)
{
mailItem.userFlg.add(userFlg[i]);
}
}
if (null != m.getFrom())
{
for (Address a : m.getFrom())
{
mailItem.from.add(MimeUtility.decodeText(a.toString()));
}
}
if (null != m.getReplyTo())
{
for (Address a : m.getReplyTo())
{
mailItem.replyTo.add(MimeUtility.decodeText(a.toString()));
}
}
if (null != m.getRecipients(RecipientType.TO))
{
for (Address a : m.getRecipients(RecipientType.TO))
{
mailItem.to.add(MimeUtility.decodeText(a.toString()));
}
}
if (null != m.getRecipients(RecipientType.CC))
{
for (Address a : m.getRecipients(RecipientType.CC))
{
mailItem.cc.add(MimeUtility.decodeText(a.toString()));
}
}
if (null != m.getRecipients(RecipientType.BCC))
{
for (Address a : m.getRecipients(RecipientType.BCC))
{
mailItem.bcc.add(MimeUtility.decodeText(a.toString()));
}
}
} catch (UnsupportedEncodingException ex)
{
ex.printStackTrace();
} catch (MessagingException ex)
{
ex.printStackTrace();
} finally
{
}
}
}
LINUXでUSBハードディスクの増設をするのにデバイスが足りない!!
えっーーつと
デバイスを追加するために/devの中を見てみると、sda~sdhまでしかない
そこで、デバイスの追加をするコマンドはなんだっけ・・・・・・
あっ!思い出した
mknod sdi b 8 128
mknod sdi1 b 8 129
これでよかったっけ!!
後はパーティションを切って、フォーマットして終わり
何故かRUBYの勉強中ということで、環境設定をする
-
http://rubyinstaller.org/download.html
上記サイトからRuby 1.8.6-p26 (Final) を選択してダウンロード
ダウンロードしたファイルを実行し、インストールフォルダーをc:\ruby とした。 -
http://mergedoc.sourceforge.jp/ から3.4 eclipse Ganymedeを選択して、Ruby 環境をダウンロードする。
ダウンロードしたファイルを解凍して、eclipseを起動する。 -
RubyGemsを更新する
下部のウィンドウズにすべてのGEMSを更新するがあるので、最新にする。 -
新しいRailsプロジェクトを生成すると、「gem でRailsをインストールしますか」と
聞いてくるので、これをインストールする。 -
新しいRailsプロジェクトを生成する。
必要なフォルダはすべて自動生成される。 -
MySql-gem のインストール
MySqlを使用するのでいるらしい・・
コマンドプロンプトより以下のコマンド
gem install mysql -
ジェネレータウィンドウでHello World の作成
パラメータに hello index を入れて実行
XCOPY でメモリーが足りません
バックアップを取る時、世の中にはいっぱいバックアップソフトがあるですが、いろいろインストールするのもめんどくさいので、私はXCOPYを使っています。
xcopy /E/C/R/D/Y コピー元のフォルダ コピー先のフォルダ
といった具合に、ファイルのタイムスタンプを見て、自動的にコピーをしてくれます。
1998年からズーットこの方法でやってきたのですが、先日ふと見てみるとバックアップ先にバックアップ元にあるべきデータがないではないですか。
「どうして???」
調べてみると、コピー元ファイルに255バイトを超えるパスがあると「メモリーが足りません」なるらしい。
そういえば、最近はやたら長い日本語のフォルダー名やファイル名を付けることが多い。そう思っていろいろパス長を短くする努力を行って、なんとか最後までバックアップは完了した。
XCOPYなんて、MSDOS時代の過去の遺物を使用し続けられるのも、そろそろ終わりなのかな。
次は、対策を練らなくてはと思う。
REDHAT EL5 でPPTPサーバの設定
- pppのインストール たいていはすでに入っている
yum install ppp - pptpdのパッケージの取得
pptpdにはpoptopを使用するのでパッケージの取得
wget http://poptop.sourceforge.net/yum/stable/rhel5/x86_64/pptpd-1.3.4-1.rhel5.1.x86_64.rpm poptopのインストール
rpm -ivh pptpd-1.3.4-1.rhel5.1.x86_64.rpm/etc/pptpd.conf の設定localip 192.168.123.10 <- ローカルIP
remoteip 192.168.100-150 <- クライアントに割り付けるIPアドレス接続オプションの設定(DNSやWINS等)
/etc/ppp/options.pptpd を編集する
ms-dns 208.67.222.222
ms-dns 208.67.220.220
接続ユーザIDとパスワードの設定
/etc/ppp/chap-secrets を編集する
# Secrets for authentication using CHAP
# client server secret IP addresses
username pptpd password *
username2 pptpd password2 *
ルーティングの設定
このサーバ以外にアクセスする場合はルーティングの設定が必要
echo 1 > /proc/sys/net/ipv4/ip_forward
その他ファイアウォールはiptablesで行う
クライアントからの接続を受けるため、このサーバは以下のプロトコルを受け付けなければならないので要注意
gre プロトコル番号 47 番
tcp 1723
Cygwin Xサーバでredhat5のデスクトップを表示する
Custom.confに以下の2行を設定するだけ!
[security]
AllowRemoteRoot=true
[xdmcp]
Enable=true
LINUX REDHAT5でのSAMBAの設定 ユーザ認証で誰でも使えるようにする
またまたいろんな仕事
Windowsサーバを使用せずにLINUXでファイル共有サーバを設定したいということで、SAMBAを設定する。
みんなが共有できるフォルダーが必要ということ。
ゴミ箱もあった方がよいのですが、SWATで設定できないため、smb.confを直接変更しました。
[global]
netbios name = KYOUYUSV
server string = Samba Server Version %v
map to guest = Bad User <——ここで、だれでもアクセスできるようにする
passdb backend = tdbsam
ldap ssl = no
cups options = raw
vfs objects = recycle <——ゴミ箱宣言
[homes]
comment = Home Directories
read only = No
browseable = No
[printers]
comment = All Printers
path = /var/spool/samba
printable = Yes
browseable = No
[みんなで共有]
path = /home/みんなで共有
read only = No
guest ok = Yes
recycle:repository = .recycle <——ゴミ箱のフォルダ名
recycle:keeptree = yes <——ディレクトリ構造を維持してごみ箱に移動するか否か
recycle:touch = yes <——ファイルがごみ箱に移されたときに、ファイルのアクセス日を変更するか否か
recycle:versions = yes <——同名のファイルがごみ箱にある場合、別名(「Copy #x of ファイル名」)で保存するか否か
recycle:maxsize = 0 <——ごみ箱に移動するファイルの上限をbyte数で指定
PHPからMySqlに接続するのにはまりまくり・・・socket の設定のずれ
TurboLinux 11 Server でjoomlaを動かそうと思ったら。
「Unable to connect to the database:Could not connect to MySQL」こんなメッセージ
どうちて?!?!?!?! コマンドでmysqlは動くのに~~~~~
ああでもない・・こうでもない・・ともがき苦しむこと3時間
わかったこと
/etc/my.cnf
では
socket=/var/lib/mysql/mysql.sock
こうなっているのに
php.iniはデフォルトのまま
phpinfoで調べてみると
| MYSQL_SOCKET | /tmp/mysql.sock |
どうしてこうなるのォォォ
php.ini ファイルにこう書いて一件落着
mysql.default_socket = /var/lib/mysql/mysql.sock
こういうことって精神的にまいるのよね。どうにかしてねTurboLinuxさん。
CentOSだとこういうことはないよ。
C#で受信スレッドを使ったTCP/IP受信オブジェクト
久しぶりにC#でTCP/IPの通信オブジェクトを作成することになった。
クライアントから数値が飛んでくるので、それを受信したらイベントで渡すプログラム。
メインはWindowsフォームで、内部は2段スレッド処理。
イベントは別スレッドになるので、ちょっとてこずったがこんなもんかいという感じ。
もう少しいい方法があったら誰かおしえてちょ!
接続待ちスレッドクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace TcpClass
{
public class TcpReceiveEventArgs : EventArgs
{
public TcpReceiveEventArgs(long Temperature)
{
this.Temperature = Temperature;
}
private long temperature;
public long Temperature
{
get { return temperature; }
set { temperature = value; }
}
}
public delegate void TcpReceiveEventHandler(long temperature);
public class TcpReceive
{
public event TcpReceiveEventHandler onTcpReceive;
private int portNo;
// スレッド停止命令用
private bool stop_flg = false;
public TcpReceive(int portNo)
{
this.portNo = portNo;
// 接続待ちのスレッドを開始
Thread thread = new Thread(new ThreadStart(ListenStart));
// スレッドをスタート
thread.Start();
}
public void Dispose()
{
stop_flg = true;
GC.SuppressFinalize(this);
}
/**
* 接続待ちスレッド本体
*/
private void ListenStart()
{
// Listenerの生成
TcpListener listener = new TcpListener(IPAddress.Any, this.portNo);
// 接続要求受け入れ開始
listener.Start();
while (!stop_flg)
{
// 接続待ちがあるか?
if (listener.Pending() == true)
{
// 接続要求を受け入れる
TcpClient tcp = listener.AcceptTcpClient();
TcpReceiveWorker rcv = new TcpReceiveWorker(tcp, this);
Thread thread = new Thread(new ThreadStart(rcv.TCPClientProc));
// スレッドをスタート
thread.Start();
}
else
{
Thread.Sleep(0);
}
}
// 接続待ち終了
listener.Stop();
}
protected virtual void OnReceiveEvent(long temperature)
{
if (onTcpReceive != null)
{
onTcpReceive(temperature);
}
}
internal void RiaseEvent(long temperature)
{
OnReceiveEvent(temperature);
}
}
}
データ受信スレッドクラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Collections;
namespace TcpClass
{
class TcpReceiveWorker
{
private TcpClient tcp = null;
TcpReceive rcv = null;
public TcpReceiveWorker(TcpClient tcp,TcpReceive rcv)
{
this.tcp = tcp;
this.rcv = rcv;
}
public void TCPClientProc()
{
NetworkStream st = tcp.GetStream();
ArrayList aryList = new ArrayList();
long count = 0;
do
{
int nret = st.ReadByte();
if (nret < '0' || nret > '9')
{
break;
}
if (nret != -1)
{
aryList.Add((byte)nret);
}
count++;
if (count > 8 ) break;
} while (tcp.Connected == true);
// ソケットを閉じる
tcp.Close();
// 受信したものをbyte配列に変換
byte[] byt = new byte[aryList.Count];
for (int i = 0; i < aryList.Count; i++)
{
byt[i] = (byte)aryList[i];
}
string strFromByte = Encoding.ASCII.GetString(byt);
long ret = long.Parse(strFromByte);
rcv.RiaseEvent(ret);
}
}
}
データ送信クラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace TcpClass
{
public class TcpSend
{
public string hostName;
public int portNo;
public TcpSend(string hostName,int portNo)
{
this.hostName = hostName;
this.portNo = portNo;
}
public Boolean send(long value)
{
try
{
// クライアント用のソケットを作成する
TcpClient cl = new TcpClient();
// サーバーへ接続する
cl.Connect(hostName, portNo);
// 接続したソケットからNetworkStreamを取得
NetworkStream stream = cl.GetStream();
Encoding encode = Encoding.Default;
// 送信する文字列をバイト配列に変換
// この際に、エンコードも同時に行う。
string s = value.ToString();
byte[] bytData =
encode.GetBytes(s);
// 書き出しを行う。
stream.Write(bytData, 0, bytData.Length);
// フラッシュ(強制書き出し)
// これを行わないと、確実にネットワークに流れない。
stream.Flush();
// ソケットをクローズ
cl.Close();
}
catch (SocketException eSocket)
{
System.Diagnostics.Debug.Write(eSocket.Message);
return false;
}
catch (Exception ex)
{
System.Diagnostics.Debug.Write(ex.Message);
return false;
}
return true;
}
}
}
イベントがクラスなのでフォームのデータを変更するときに注意が必要なんでこんな感じ
void c_onTcpReceive(object sender, TcpReceiveEventArgs eventCode)
{
CheckForIllegalCrossThreadCalls = false; /* 別スレッドでのアクセスを許可する */
this.textTemperature.Text += eventCode.Temperature;
this.textTemperature.Text += "\n";
}
実はイベントを受け取るとき別スレッドで受け取るため下のやり方が正しい かなりややこしいが、昔ならウィンドウメッセージを使っていたから、この方が簡単化もしれない。でもややこしい!
private void button1_Click(object sender, EventArgs e)
{
c = new TcpReceive(10000);
c.onTcpReceive += new TcpReceiveEventHandler(c_onTcpReceive);
}
void c_onTcpReceive(long temperature)
{
if (textTemperature.InvokeRequired)
{
Invoke(new delSetTemperature(setTemperature), new object[] { temperature });
}
else
{
setTemperature(temperature);
}
}
delegate void delSetTemperature(long temperature);
void setTemperature(long temperature)
{
textTemperature.Text += temperature;
textTemperature.Text += "\n";
}
PHPでExcelを生成できないかなぁ~なんて思っていたら
PHPでExcelを生成できないかなぁ~なんて思っていたら
なんとあるではないか
名前は、[PHPExcel] なんとべたな名前。
さっそく使ってみたら、こんな感じでできました。
$reader = PHPExcel_IOFactory::createReader(‘Excel2007’);
$xl = $reader->load(configure::$excel_folder . ‘/’ . ‘scg_base.xlsx’);
$xl->setActiveSheetIndex(0);
$sheet = $xl->getActiveSheet();
$sheet->setCellValue(‘B1’,$_POST[‘sel_table’]);
$i = 3;
foreach($array as $key => $value)
{
$sheet->setCellValue(‘A’ . $i,$value[‘fieldname’]);
$sheet->setCellValue(‘B’ . $i,$value[‘fieldtype’]);
$sheet->setCellValue(‘C’ . $i,$value[‘len’]);
$sheet->setCellValue(‘D’ . $i,$value[‘period’]);
$sheet->setCellValue(‘E’ . $i,$value[‘max_len’]);
$sheet->setCellValue(‘F’ . $i,$value[‘comment’]);
$sheet->setCellValue(‘G’ . $i,$value[‘type’]);
if($main_key[‘fieldname’] == $value[‘fieldname’])
{
$sheet->setCellValue(‘H’. $i,’○’);
}
else
{
$sheet->setCellValue(‘H’. $i,”);
}
if($value[‘field’]) $sheet->setCellValue(‘I’ . $i, ‘○’);
$sheet->setCellValue(‘J’ . $i,$value[‘ime_mode’]);
if($value[‘search’]) $sheet->setCellValue(‘K’ . $i,’○’);
if($value[‘necessary’]) $sheet->setCellValue(‘L’ . $i,’○’);
$i ++;
}
$writer = PHPExcel_IOFactory::createWriter($xl, ‘Excel5’);
$uniqid = uniqid(‘aa’,true);
$filename = configure::$excel_folder . ‘/’ . $uniqid .”.xls”;
$writer->save($filename);