通过google voice发送短信

手机上一直装了几个应用,用来给美国手机发送短信,每次都需要登录,比较麻烦。最近也想做一个小应用,其中通过手机发送验证码,觉得google voice最能满足这个要求,反正免费的不用白不用。

在网上找了一些源码,看看如何通过程序来发送短信,基本由三个版本,两个php版,其中一个zend加密版本,被pass掉,另外一个可能接口有些变更,好像发送不太成功。另外还找到一个java版本,测试了一下,可以成功发送,感谢原作者xinghuo.yao的无私奉献。从google code下载的代码,貌似作者是做了一个smsbot,但是我不需要这么复杂的功能,只把googlevoice实现部分摘出来了。

public class GoogleVoice implements Serializable {

/**
*
*/
private static final long serialVersionUID = 5889296580959689523L;
private String email;
private String password;

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

private String auth;
private String rnr;

private long lastSessionTime = 0;

public long getLastSessionTime() {
return lastSessionTime;
}

public void setLastSessionTime(long lastSessionTime) {
this.lastSessionTime = lastSessionTime;
}

public GoogleVoice(String email, String password)
throws AuthenticationException {
this.email = email;
this.password = password;
signIn();
}

private void signIn() throws AuthenticationException {
retrieveLoginAuth();
retrieveRnr();
lastSessionTime = System.currentTimeMillis();
}

public boolean sendSms(String mobile, String message) {
if (!checkSession())
return false;
try {
String payload = “id=&phoneNumber=” + mobile + “&text=”
+ URLEncoder.encode(message, “UTF-8”) + “&_rnr_se=”
+ URLEncoder.encode(rnr, “UTF-8”);
String data = fetchData(“https://www.google.com/voice/sms/send/”,
payload, auth);
// Should return {“ok”:true,”data”:{“code”:0}}
if (data.contains(“:true”))
return true;
else
return false;
} catch (Exception e) {
return false;
}
}

private boolean checkSession() {
if (System.currentTimeMillis() – lastSessionTime >= 1800000l)
return false;
lastSessionTime = System.currentTimeMillis();
return true;
}

private void retrieveLoginAuth() throws AuthenticationException {
String payload = “accountType=GOOGLE&Email=” + email + “&Passwd=”
+ password + “&service=grandcentral&source=” + “GAE”
+ “-GoogleVoiceTool”;
try {
String data = fetchData(
“https://www.google.com/accounts/ClientLogin”, payload,
null);
int index = data.indexOf(“Auth=”);
if (index != -1 && index + 5 < data.length())
auth = data.substring(data.indexOf(“Auth=”) + 5).trim();
if (StringUtil.isEmptyOrWhitespace(auth))
throw new AuthenticationException(“Get Login Auth failed”);
} catch (Exception e) {
throw new AuthenticationException(e.getMessage());
}
}

private void retrieveRnr() throws AuthenticationException {
try {
String data = fetchData(“https://www.google.com/voice/m/”, null,
auth);
Pattern p = Pattern.compile(
“<input.*?name=\”_rnr_se\”.*?value=\”(.*?)\””,
Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(data);

if (m.find())
rnr = m.group(1);
if (StringUtil.isEmptyOrWhitespace(rnr))
throw new AuthenticationException(“Get rnrSEE failed”);
} catch (Exception e) {
throw new AuthenticationException(e.getMessage());
}
}

private String fetchData(String url, String payload, String auth)
throws Exception {
HttpURLConnection con = (HttpURLConnection) new URL(url)
.openConnection();
if (auth != null)
con.setRequestProperty(“Authorization”, “GoogleLogin auth=” + auth);
con
.setRequestProperty(
“User-Agent”,
“Mozilla/5.0 (iPhone; U; CPU iPhone OS 2_2_1 like Mac OS X; en-us) AppleWebKit/525.18.1 (KHTML, like Gecko) Version/3.1.1 Mobile/5H11 Safari/525.20”);
con.setRequestProperty(“Content-Type”,
“application/x-www-form-urlencoded”);
if (payload == null)
con.setRequestMethod(“GET”);
else {
con.setDoOutput(true);
con.setRequestMethod(“POST”);
OutputStream os = con.getOutputStream(); // 输出流,写数据
os.write(payload.getBytes(“UTF-8”));
os.flush();
os.close();
}
int code = con.getResponseCode();
if (code == 200) {
String response = getContent(con.getInputStream(), code);
con.disconnect();
return response;
} else {
String response = getContent(con.getErrorStream(), code);
con.disconnect();
throw new AuthenticationException(response);
}
}

private String getContent(InputStream in, int code) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(in,
“UTF-8”)); // 读取结果
StringBuffer sb = new StringBuffer(“”);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append(“\r\n”);
if (code != 200 && line.startsWith(“Error=”)) {
reader.close();
return line.substring(6);
}
}
reader.close();
if (code != 200)
return String.valueOf(code);
return sb.toString();
}

public static void main(String[] args) throws AuthenticationException{
GoogleVoice gv = new GoogleVoice(“用户名”, “密码”);
if (gv.sendSms(“手机号码”, “hello”))
System.out.println(“短信已发送至:”);
else
System.out.println(“短信未发送”);
}
}

 

 

早在一两年前,gv貌似还能全世界发短信,后来只限定在美加,不过对于我来说这个已经足够了。再次感谢作者无私奉献,感谢google无私奉献,但愿google别把这个接口给封了。

Dana’s Travel in China

IMG_4739 IMG_4744   IMG_4746IMG_4644 IMG_4647 IMG_4668 IMG_4673 IMG_4729

IMG_4806

Dana, one of my america friends, came to China and traveled in several cities. In every cities, he got great passion from the students. He is a religious Christian.

One of my classmates asked him, why you come to China. He said, everyone is like a mirror, which can reflect the light of God. We could help others just like the mirror reflecting the light.

He does help the students a lot in Springfield, He spends 25 hours to help the student, even 35 hours a week, that is to say, 5 hours per day.  That why he can receive the great passion here. I don’t think if other professor who also comes from Springfield can receive better than him.

Common people, but great man.

Since I am not a Christian, but I want to thank him.

wordpress首页只显示指定栏目

这个blog建了挺久了,一直是乱七八糟的帖子混在一起,首页比较混乱,所以想把首页只放一些原创的非技术的帖子。

在网上找了很多方法,有的需要修改源代码,有的装插件。修改源代码的方法不适合将来升级(虽然说上次升级导致博客无法打开),所以还是用插件比较好。

网上推荐用Front Page Excluded Categories装了这个插件似乎不生效。所以又装了Ultimate Category Excluder,装上并启用以后在setting里面Category Exclusion里面选上你要过滤掉的目录就可以了。这个插件的神奇之处在于,你可以选择只滤掉首页,feed,search等不过滤,这样既可以隐藏首页不想要的东西,又不影响搜索引擎及订阅的内容。赞一个。