(専攻科実験)Perlでのメール送信
専攻科の実験で、RSS による情報フィードの活用のテーマのプログラム作成中。 実験学生が、作ってみたいプログラムの案にメールの事例が多かったので、 メールの送信方法について記載しておく。
もっとも簡単なメール送信例
メールを送るためには、メール形式について理解が必要となるので、以下の資料参照。
特に、日本語などの様々な言語でメールを送る場合には、 メールヘッダの"Content-Type:… charset=…"によって、送信する文字コードなどを 指定すれば良い。ただし、日本の古いガラケーでは、JIS コード以外だと文字化けする 場合も多いため、特に問題がないのなら日本語でメールを送るには、 JISコード(ISO-2022-JP)にすべきである。
以下に、最も単純な日本語メールを送るサンプルプログラムを示す。
#!/usr/bin/perl use Jcode ; use Email::MIME ; use Email::MIME::Creator ; # メールの形式に応じたデータを作る my $mail = Email::MIME->create( # メールヘッダの必須パラメータ header => [ # (注) headerは配列へのリファレンス # "foo@example.co.jp"と書くと # @exampleの部分が配列とみなされるので''を使う。 From => 'foo@example.co.jp' , To => 'bar@example.co.jp' , # ヘッダでの漢字は、MIME形式でエンコードしないとダメ。 Subject => Jcode->new( "実験" )->mime_encode() , ] , # その他のパラメータ attributes => { # (注) attributesはハッシュへのリファレンス content_type => 'text/html' , charset => 'ISO-2022-JP' , encoding => '7bit' , } , # メールの本文 body => Jcode->new( "こんにちは" )->jis ) ; # sendmail を使ってメールを送る。 # "-t" オプションをつけるとヘッダ部を追加できる # open( FH , "|..." ) で出力をプログラムにパイプで渡す。 open( FH , "| /usr/sbin/sendmail -t" ) or die( "Can't open sendmail" ) ; print FH $mail->as_string ; close( FH ) ;
台湾への工場見学旅行のお土産もらいましたぁ。
今週1週間、3EIの学生さんは工場見学旅行で、今年は前年に引き続き台湾となりました。 先程、先に無事にもどられた西先生より、おみやげを頂きました。 特に大きなトラブルもなく、見学先の大学との学生間交流もできたようでした。
まだ、3EIの学生さんは自主見学旅行の途中でしょうが、無事に帰ってきてくださいませ。
『今日は1限目から3EIの授業、先週のネタからすると××の説明するぞ!!』と 教室に向かったけど、誰もいませんでした…
# 気づくの遅っ!!
MyJVNによる更新チェック
最近のウィルスなどの侵入手口では、 古い Java を悪用した手口が多いらしい。
このことから、よく利用されているソフトの更新チェックが 重要となる。しかし、すべてのソフトの更新確認は、大変である。 でも、日本のセキュリティセンターの JPCERT などが監修し、 ブラウザで古いソフトをチェックしてくれるサービス MyJVN がある。
さっそく自宅マシンで実行したが、Java は自動更新がかかるので、 大丈夫であったが、ブラウザの FireFox などで警告がでてきた。 メインブラウザが Chrome だけど、ひとまず関連ソフトの更新を行った。
(専攻科実験)RSSを用いた情報活用
インターネットでは、様々な情報が提供されているが、 これらの情報を効率よく見つけ出すには、労力を要する。 このため、インターネット上の情報サイトでは、 RSS(Rich Site Summary) と呼ばれる XML をベースとした、サイトの概要情報を提供している。 これらの RSS の情報は、 フィードリーダ というソフトを使うことで、 そのタイトル・概要をシンプルに表示してくれることから、 読者が興味のある記事を見つけやすくなる。
今回は、これらの RSS 形式のデータを活用するために、 自分の作成した情報の RSS データを作成したり、 一般に公開されている RSS フィードを読み込み解析し、 2次利用できるようにしたり、自分たちの使うインターネットと連動できる プログラム開発を、文字列処理の得意なプログラム言語である、Perl や PHP を用いて 作成することを目指す。
RSSと解析ライブラリ
RSSには、その発展の歴史の中から、少しづつ書式を変えながら発展してきた。 最初は、RDF と呼ばれる形式であったが、RSS 2.0 に発展する中で、 XML 形式による書式となった。 この他にも、RSS の問題点を改良した Atom 形式なども提案されている。
RSSのデータ形式は様々で、全ての形式に対応したプログラム作成は本来難しい。 しかし Perl や PHP では、便利なパーサ・ライブラリがあるので、RSSの情報の中から、 希望する情報だけを簡単に抽出することが可能となっている。
Perl で RSS 形式のデータを扱うために、今回は "XML::FeedPP"モジュールを使用する。 このライブラリは、RSS/RDF/Atom など様々な フィード形式に対応している。 XML::FeedPP の解説サイトには、データを入力・出力するなどの手続きの例が、 いくつか記載されているので、これらのサンプルプログラムを元にプログラムを作成せよ。
#!/usr/bin/perl # 使用するモジュールを選ぶ use XML::TreePP ; # use 文は C言語の #include みたいなもの。 use XML::FeedPP ; # 日本語の文字コード変換モジュール use Jcode ; # 読み込むフィード my $source = 'http://use.perl.org/index.rss'; # my は局所変数宣言 # RSSデータを解析し読み込ませる my $feed = XML::FeedPP->new( $source ); # 記事全体の情報を表示 my $title = $feed->title() ; # Jcode->new( "文字列" ) に対する変換コード(以下が利用可) # ->utf8 , ->unicode , ->jis , ->sjis , ->euc print "Title: ", Jcode->new( $title )->utf8 , "\n"; print "Date: ", $feed->pubDate(), "\n"; # 個別の記事の情報を表示 foreach my $item ( $feed->get_item() ) { print "URL: ", $item->link(), "\n"; my $title = $item->title() ; print "Title: ", Jcode->new( $title )->utf8, "\n"; } # foreach文は、配列要素すべてに対する処理ループを実行 # foreach $要素 ( @配列 ) { ... }
実験方法
プログラムの実験にあたり、 ファイルの編集にはファイル共有機能を使用し、 プログラムの実行にはターミナルソフト(TeraTerm)を使用する。
最初に、実験端末に TeraTerm がインストールしてなければ、 このページ先より入手し、インストールを行うこと。
サーバに接続し、プログラムを実行するには、TeraTermPro.exe を実行し、 Host:「tsaitoh.ei.fukui-nct.ac.jp /KR=UTF-8 /KT=UTF-8」, Service:SSH で接続し、 別途指定された ユーザ名 , パスワード を利用し、Login せよ。
ファイルを編集する際には、Windows 端末のファイル共有にて、 「¥¥tsaitoh.ei.fukui-nct.ac.jp¥ユーザ名」にてアクセスし、 login 画面が出たら、ユーザ名とパスワードを入力せよ。 Windows のエディタで、ファイルを編集し保存する際には、 「文字コード: UTF-8 , 行末コード: nl」を指定すること。
(( 前述の feed.pl を実行する場合 )) $ perl feed.pl
最初の課題
上記のプログラムを動作させ、得られる結果などを確認せよ。 RSSフィードの http://…./…xml などは、Firefox などのブラウザであれば、 わかりやすいように表示をしてくれる。さらに、"ページソースを表示"などを実行すれば、 元々の XML 形式のデータを見ることもできる。
まずは、プログラムの内容などを確認したうえで、 インターネット上に掲載されている RSS フィードにどのようなものがあるか調べ、 これらの情報をどのように活用したら便利かアイデアを検討せよ。
緊急連絡システムの”~”の文字化け対策
緊急連絡システムの利用者の方から、 「URL内の”~”が文字化けして、利用者確認のURLにアクセスできない」といった トラブルがあるとのご指摘を受けた。
その方の話をまとめると、緊急連絡システムの末尾に付けられる利用者確認のURLの行が、 Docomo の SPモードメールなどで、” ̄”に書き換えられてしまうため、らしい。
送信:http://XXX.fukui-nct.ac.jp/~emc/alive.php?..... 受信:http://XXX.fukui-nct.ac.jp/ ̄emc/alive.php?.....
URLの中の”~”は、ホームディレクトリを表すために、広く一般的に用いられている URL の 記号文字であり、こんなものを書き換えてしまう SP モードメールがアホと叫びたいけど、 なんらかの対応を…と考えてみた。
緊急連絡システムのプログラムに、大きな変更を加えたくないので、 URLを “~”無しでもアクセスできるように変更し、 メール送信時に、”/~emc/…” で送信すべき場所を “~”無しのURLの ”/emc/…” で送信するように変更した。
RewriteEngine on RewriteRule ^emc/(.*)$ /~emc/\ [L]
ワード境界,共用体,列挙型
構造体の演習に引き続き、構造体の応用について説明する。
ワード境界
構造体の配列をメモリに格納する場合、ワード境界が問題となる。 最近のコンピュータでは、CPUの速度に比べ主記憶の速度は遅いため、 メモリを効率よくアクセスする必要がある。 このために、メモリ上のデータは、ワード単位で一括して読み書きされる。
struct Data { char a[ 5 ] ; int b ; short int c ; } ; struct Data array[ 10 ] ;
上記のような構造体があったとして、メモリー上に以下のように配置されていると、 array[0].b を参照する際には、04行と08行の2回のメモリアクセスがあって、 メモリ参照速度が低下する。
ワードアライメントを無視した配置 |
ワードアライメントした配置 |
このような、データを読み書きする際の、ワードの塊の境を「ワード境界」と呼ぶ。 また、右図のように、ワード境界をまたがないようにデータを配置することを、 ワードアライメントと呼ぶ。
もし、処理速度の低下より、メモリの有効利用が必要であれば、VC++であれば、”#pragma pack”や”gccの”__attribute__((packed))”などを指定する。
共用体
プログラムを作っていると、データが「名前と年齢」か「名前と住所」のどちらかで、 「名前と年齢と住所」が揃うことはない…という場合もある。この際に、”struct ..{ char name[] ; int age ; char addr[] } ; ” では、かならず3つのデータを覚えてしまい、メモリの無駄が発生するのが問題となる場合がある。 このようなときに使うのが共用体である。共用体では、中身のいずれかを覚えるために使う。 また、要素の記憶場所は共有される。
union AgeOrAddr { int age ; char addr[ 30 ] ; } ; struct NameAndAgeOrAddr { char name[ 20 ] ; union AgeOrAddr age_addr ; } ;
データの記憶場所が同じことを確認するために、以下の様な処理を実行した結果も示す。
union A { char s[4] ; int x ; } ; union A a ; // 文字列の代入 strcpy( a.s , "ABC" ) ; printf( "%8x\n" , a.x ) ; // 配列の代入 a.x = 0x12345678 ; a.s[2] = 0x99 ; printf( "%8x\n" , a.x ) ; (( 実行結果 )) 00434241 // 実験したコンピュータは Intel Xeon 11995678 // この結果より、リトルエンディアン なのが判る。
この結果は、CPUの内部が、ビッグエンディアン(68系,SPARC)か、リトルエンディアン(x86系)によって異なる。また、この順番はCPUの異なる間のネットワーク通信でも問題となることが多く、ネットワーク通信では、ビッグエンディアンを用いることになっている。
列挙型
カレンダーの処理などで、週のデータを扱う場合、日:0,月:1,火:2… と番号を振って その番号に応じてプログラムを記述する場合がある。
(( わかりにくいプログラム )) int week = なにかの週番号 ; if ( week == 3 ) { // 3がマジックナンバー 水曜日の処理 ; } (( わかりやすいプログラム )) #define SUN 0 #define MON 1 #define TUE 2 : if ( week == WED ) { // 読んでいて意味が判る 水曜日の処理 ; } (( でも週と月を整数型で扱っているだけ )) #define JAN 1 #define FEB 2 #define MAR 3 int week = 週の番号 ; week = FEB ; // エラーにはならないけど、意味的に間違い。
列挙型は、以下の様な使い方をすることで、シンプルな書き方で定数に意味をもたせることができる。このため、型の間違いの確認もできる。
enum Week { SUN , MON , TUE , ... SAT } ; enum Month { JAN , FEB , MAR , APR , MAY , ... DEC } ; enum Week week = 何らかの曜日 ; if ( week == WED ) { 水曜日の処理 ; } switch( week ) { case MON : 月曜の処理 ; break ; case WED : 水曜の処理 ; break ; // この書き方をすると、月水以外の処理が記載されていない // ことをコンパイラが警告してくれる。 } week = FEB ; // エラー:週の変数に月の値を代入することはできない。
sambaでファイルを作れても消せない
修理に出していた、学科のバックアップ用のNASが戻ってきたので、 改めて学科データの保存のための設定を行う。
samba経由でアクセスするための設定は、簡単に復旧できたが、 「ファイルを作っても消せない」という変な状況が発生。 色々やっている内に「この症状どっかで体験したよな…」というわけで、 自宅サーバの設定ファイルやらを確認するけど、思い出せない…
デジャブじゃないよな…とも思いながら、ググったら見た覚えのある 設定追加項目を発見。 OSXのファイル共有で、sambaをアクセスすると、 ファイルを作れても消せないというネタが見つかる。
[global] acl check permissions = no
こういう微妙な設定は、blog にでも残さないと、 もう一度デジャブ体験することになる…
MacBookAir OS X Mavericks
iOSの新機種なども出たようだけど、これに合わせて、 OSX Mavericks が無料で出た様子。 ということで、iMac に入れてみた。 iMacでインストール中には、「ディスクが壊れていて、インストール出来ない」 といった表示がでて、びびったけど、ディスクユーティリティで 修復をかけたら、無事インストールができた。
今、2台目ということで、MacBook Air にインストール中。
Mavericksって、マイナーバージョンアップかと思って、 気軽に適用したけど、10.8.x → 10.9 だったのね。 お陰で、プリンタ(Canon LBP3300)が動かなくなった。 メーカーページを見ると、11月中頃にはドライバ公開って出ていた。 ということで、当面は、卒研室のプリンタを借りることになりそう。
でも、頻繁に卒研室も面倒なので、Parallels の Windows7 に、 LBP3300のドライバ入れてみた。ちょいと面倒だけど、いちいちコピーするよりは楽かな。
構造体を使った課題(オブジェクト指向っぽく)
3年の授業では、構造体を使った説明もできたので、 構造体を使った課題の時間とした。
課題テーマ
名前と誕生日といった複合データを読み込み、何らかの処理を施す プログラムを構造体を使って記述する。 前回のファイル処理のプログラムを拡張して作成してよい。
ただし、前回授業では、オブジェクト指向の考え方について説明をしたので、 1件分のデータを入力する関数・出力する関数などを使って、 極力オブジェクト指向っぽく記述すること。(必須ではない)
いつも授業で寝ている学生さんだけど、課題中に横を通る度に、 「何か見ていたであろう画面」を消すヤツがいる。 うーん、演習室の教員用端末には、授業中の全端末のデスクトップ画面を閲覧する 機能があるのを今さら知らないのだろうか… ソフトを立ち上げ、その学生のデスクトップを見ると、 「2chまとめサイト」を見てやがる…
個人特定で怒るのもなんなので、 「教員端末は全端末監視ができるけど、2chみてるのがいるけど…」と 全員に警告しておいた。