Hatena::ブログ(Diary)

徒なる研究あるいはイアトロ化学者 RSSフィード

2008-10-12

【告知】MakeYourDayは近日中にサービス停止します。

ご好評いただいてきました MakeYourDay ですが、物理的な事情によりサービスを停止します。

サービス停止日は10/19頃を予定しています。

10/18分をもって停止しました。


700人を越えるユーザ様にご利用いただいていますが、Twitterはてなブックマーク等を合わせて毎日1000通を越えるはてなダイアリー投稿メールを連続して送っており、さくらインターネットレンタルサーバのメールサーバスパム扱いされて送信を拒否されています。*1

はてなダイアリーAtomPubを使う*2Gmailなど他のSMTPサーバを使う*3・新規登録を中止して既存ユーザだけで続ける・自分のfollowing/follower関係だけ救済する*4などを考えましたが、いずれも明朗な解決策とはいえず、サービスを停止することに決めました。


Twitterのログを投稿する部分のスクリプト(一部修正済み)を下記に掲載します。

SMTP認証周りはさくらレンタルサーバ スタンダードでの仕様です。cronで毎日午前3時頃に動かしていました。

require 'net/smtp'
require 'net/http'
require 'nkf'

mailserver="さくらID.sakura.ne.jp"
maildomain="さくらID.sakura.ne.jp"
mailid="さくらメールID@さくらID.sakura.ne.jp"
mailpass="さくらメールIDパスワード"
mail="さくらメールID@さくらID.sakura.ne.jp"
backupmail="バックアップ送信用メールアドレス"

hatenad={"はてなID" => "はてなダイアリー投稿用アドレス"}	#"@d.hatena.ne.jp"と".g.hatena.ne.jp"は省く
twitter={"はてなID" => "ツイッターID"}
twittertitle={"はてなID" => "はてなダイアリー投稿時のタイトル"}	#"[ライフログ]今日のツイッター"とか

t=Time.now-60*60*24
$yesterday=Time::mktime(t.year,t.month,t.day,3,0,0)		#午前3時から現在までのログを投稿


### スクレイピング

def fetch(p,id)
  rt=0
  begin
    body = Net::HTTP.get( "twitter.com" , "/"+id+"?page="+p.to_s )
  rescue Exception => err
    sleep 10
    rt+=1
    retry if rt<3
    $stderr.print err,":",id,"\n"
    $yesterday
  else

    $stderr.print "404:That page doesn't exist!:",id,"\n" if /That page doesn't exist!/=~body

    body.split(/<\/ul>|<\/td>/).each{|line|
      if p==1 && /<p class="entry-title entry-content">\s*(.+)\s*<\/p>\s*(<a href="http:\/\/twitter\.com\/[^\/]+\/statuses\/\d+">\.\.\.<\/a>|)<div style="float:right;margin-top:-5px;"><div id="status_actions_\d+" class="status_actions">\s*<\/div>\s*<\/div>\s*<p class="meta entry-meta">\s*<a href="http:\/\/twitter\.com\/[^\/]+\/statuses\/(\d+)" class="entry-date" rel="bookmark"><abbr class="published" title="(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d)\:(\d\d)\:\d\d\+00\:00">/=~line
        $comment << $1
        $link << $3
        $date << Time::mktime($4.to_i,$5.to_i,$6.to_i,$7.to_i,$8.to_i)+60*60*9
      elsif      /<span class="entry-content">\s*(.+)\s*<\/span>\s*(<a href="http:\/\/twitter\.com\/[^\/]+\/statuses\/\d+">\.\.\.<\/a>\s*|\s*)<span class="meta entry-meta">\s*<a href="http:\/\/twitter\.com\/[^\/]+\/statuses\/(\d+)" class="entry-date" rel="bookmark"><span class="published" title="(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d)\:(\d\d)\:\d\d\+00\:00">/=~line

        $comment << $1
        $link << $3
        $date << Time::mktime($4.to_i,$5.to_i,$6.to_i,$7.to_i,$8.to_i)+60*60*9
      end
    }
    $date[-1] ? $date[-1] : $yesterday
  end
end


### メイン

hatenad.each{|user,mailto|

  next if mailto.to_s=="" || twitter[user].to_s==""

  $mailout=""
  page=1
  $last=""
  $comment=[]
  $link=[]
  $date=[]

  while page<11 && fetch(page,twitter[user])>$yesterday 	#11ページから先のpostは破棄
    page+=1
  end
  $comment.each_with_index{|c,i|
    mailbody=""
    if $date[i]>$yesterday
      mailbody << "[http://twitter.com/"+twitter[user]+"/statuses/"+$link[i]+":title="+("0"+$date[i].hour.to_s).slice(-2,2)+":"+("0"+$date[i].min.to_s).slice(-2,2)+"] "
      mailbody << c.gsub(/<a href="([^\/][^"]+)"[^>]*>[^<]*<\/a>/,'\1').gsub(/<[^>]*>/,'').gsub("&gt;",">").gsub("&lt;","<").gsub("&quot;",'"').gsub("&amp;","&")
      mailbody << "\n"
    end
    $mailout=mailbody+$mailout
  }

### メール送信

  if $mailout!=""
    retry_count=0
    begin
      address=mailto+'@d.hatena.ne.jp'
      address=mailto+'.g.hatena.ne.jp' if mailto=~/@/
      Net::SMTP.start( mailserver, 25, maildomain, mailid, mailpass, :login ) {|smtp|
        smtp.send_mail <<EOM, mail, address, backupmail
From: #{mail}
To: #{address}
Subject: =?iso-2022-jp?B?#{NKF.nkf('-EjMB',twittertitle[user])}?=
Content-Transfer-Encoding: 7bit
Content-Type: Text/Plain; charset=iso-2022-jp

#{NKF.nkf('-Wj',$mailout)}
EOM
      }								#↑はてなダイアリー投稿時のタイトルがEUCなので'-EjMB'
    rescue => err
      $stderr.print user,":",address,":",err,"\n"
      retry_count+=1
      if retry_count<2
        sleep 10
        retry
      end
    end
  end
}

*1:「550 5.7.1 Command rejected, Your sent mails reached the limit.」というエラーですが、送信済みメールはサーバに蓄積されておらず、毎日途中までは送信成功しており、スパムと見做されて拒否されていると考えていいと思います。

*2:新たにはてなダイアリーパスワードを預かる必要があります(追記:LoudTwitterというサービスがあるようです)。現状はてなダイアリー投稿用メールアドレスを預かっているのも充分危険ですが、ダイアリー投稿しかできませんし、ユーザー側で再設定できるので。

*3:結局スパム扱いされることになるでしょう(追記:Gmailは500通/日らしい)。自前でメールサーバを立てるのはメンテナンス負担が大きい。

*4:不公平。

通りすがり通りすがり 2008/10/13 03:53 1000通連続は厳しいですね・・・。
時間差で30分おきに50通づつメールを送るなどしたら解決にならないでしょうか?

こっそりさんこっそりさん 2008/10/13 08:40 さくらのライトとスタンダードは1時間あたり1000通がリミットです
メーリングリスト機能なんかでもこの制限で1日あたり2万4千通までしか送れないようになってたはずです
大量送信に関する明示的な上限数はWeb上であまり喧伝するもんじゃないですが一応

kokorohamoekokorohamoe 2008/10/13 16:21 はてなにしかメールを送らないというならば、USENあたりに回線を借りて、自サバ運営すればよいのではないでしょうか?そんなに、手間もかかりませんし。
USENさんの営業さんとか、まぁ、Bフレッツ系の営業さんとか紹介しましょうか?

worrisworris 2008/10/13 23:17 >こっそりさん
情報ありがとうございます。
1000通/hであれば、ユーザ数の伸びしろがそれほどないと考えると、なんとかなりそうな気もします。
ただ他にも、タイムアウト等で失敗した場合の再試行を実装していない・無効なアカウントの削除が手動・はてなダイアリー投稿先が無効だった場合の対処(エラーメールは返らない)などの問題がありまして、一旦打ち切りとさせていただきたいと思います。

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。

トラックバック - http://d.hatena.ne.jp/worris2/20081012/1223828088