WSH: Thunderbird, dialing, get mail, disconnect

22nd October 2005 - 15:28

Disclaimer: то, что получится в итоге, — написано под один тип ОС, определённые настройки модемного соединения и, уверен, не без косяков (as usual).

Есть: Thunderbird и dial-up.

Хочется при запуске TB: автоматического соединения, забора почты и разрыва созданного соединения.

Изначально думал написать расширение, но, поковырявшись в коде, решил пойти более простым для себя путём: WSH. Итак, начнём писать наш autoDialUp.wsf…

Шаги:

  1. запустить TB;
  2. посмотреть, есть ли активные на данный момент модемные соединения и, если таковых нет, то соединиться;
  3. инициировать забор почты;
  4. дождаться окончания загрузки почты и, если модемное соединение было создано, то разорвать его.

Шаг 1.

Для запуска TB нам нужно знать где этот самый TB находится, для этого поработаем с веткой реестра HKCU\Software\Mozilla\Mozilla Thunderbird. Взяв из неё значение CurrentVersion и подставив его в {версия}\Main\PathToExe, получим путь к thunderbird.exe, который и запустим:

var WshShell = WScript.CreateObject("WScript.Shell");

try {
  var appPath = WshShell.RegRead("HKCU\\Software\\Mozilla\\Mozilla Thunderbird\\CurrentVersion");
} catch (e) {
  quit("can't find Mozilla Thunderbird application.");
} finally {
  try {
    appPath = WshShell.RegRead("HKCU\\Software\\Mozilla\\Mozilla Thunderbird\\" +
                               appPath + "\\Main\\PathToExe");
  } catch (e) {
    quit("can't find Mozilla Thunderbird application.");
  } finally {
    WshShell.Run(appPath, 7, false); //~ minimized window
  }
}

Шаг 2.

При помощи rasdial получаем сведения о наличии активного модемного соединения. Если в консоли англоязычной винды выполнить команду rasdial, то при отсутствии подключения к сети получим на выходе

C:\rasdial
No connections
Command completed successfully.

Делаем пайп на find:

var rv = WshShell.Run("rasdial | find \"No connections\" > NUL", 0, true);

Если активных соединений нет (rv == 0), то ищем в реестре имя соединения по-умолчанию и, если оно найдено, запускаем процесс дозвонки:

if (!rv) {
  try {
    var connection = WshShell.RegRead("HKCU\\Software\\Microsoft\\RAS AutoDial\\Default\\DefaultInternet");
  } catch(e) {
    quit("can't find active or default Internet connection.");
  } finally {
    rv = WshShell.Run("rasphone -d " + connection, 0, true);
    if (rv)
      connection = false;
  }
}

Теперь можно рассказать и о функции quit():

function quit(msg, inf) {
  if (connection) WshShell.Run("rasphone -h " + connection, 0, false);
  WshShell.Popup("ThunderbirdAutoMail: "+msg,0,inf?"Info":"Error",inf?64:16);
  WScript.Quit();
}

Шаг 3.

Для получения почты со всех ящиков достаточно нажать Ctrl+Shift+T… Нет-нет, руками мы этого делать не будем.

Посредством WshShell.SendKeys() можно послать любую клавишу или их комбинацию в активное окно. Активизировать окно, зная его заголовок, можно через WshShell.AppActivate(), но так как заголовок TB не обязательно будет «Mail & Newsgroups», да и при тестировании этого способа почему-то фокус передавался у меня не всегда, то просто ещё раз запустим TB:

WshShell.Run(appPath, 5, false);
//~ 5 - activates the window and displays it in its current size and position.
WScript.Sleep(100);
WshShell.SendKeys("^+t");

Шаг 4.

Зная process ID (PID) приложения и пройдясь регулярным выражением по выводу команды netstat с ключами -n -o -p tcp, можно получить информацию о сетевой активности приложения (соединения и их состояние).

Ищем PID громоптицы:

var appPID, e = new Enumerator(GetObject("winmgmts:").InstancesOf("Win32_process"));
for (; !e.atEnd() && !appPID; e.moveNext())
  if (/thunderbird\.exe/.test(e.item().Name))
    appPID = e.item().Handle;

if (!appPID)
  quit("can't find Mozilla Thunderbird process.");

Можно было бы пройтись по выводу netstat командой findstr, но интереснее подать его на вход нашему же скрипту:

do {
  WScript.Sleep(10000);
  rv = WshShell.Run("netstat -n -o -p tcp | cscript " +
                    WScript.ScriptName + " \"" + appPID +
	                "\" //Job:RegTester", 0, true);
} while (!rv); //~ 1=2 in Job:RegTester

quit("work done.", true);
<job id="RegTester">
  <script language="JScript">
  var appPID = WScript.Arguments.Item(0), netStatOut = WScript.StdIn.ReadAll();
  if (new RegExp("\\:(110|25|80|143)\\s*([A-Z_12]*)\\s*" + appPID + "\\n").test(netStat))
    WScript.Quit(); //~ pop3, smtp, http, imap connections with TB PID
  1 = 2;
  </script>
</job>

autoDilaUp.wsf (3 kb).

В каких условиях это работало: W2k3 (англицкий); TB 1.0.6 (en); одно модемное соединение, выставленное по-умолчанию и не запрашивающее логинов/паролей.

Ещё один дисклаймер: мне малоинтересна полезность этого скрипта и, как уже говорилось в самом начале, его безбажность. Просто хотелось посмотреть некоторые возможности манипулирования приложениями при помощи WSH.

Пара слов о создании расширения на эту тему: можно написать компоненту и из неё создавать/разрывать соединение посредством того же rasphone. Там (в компоненте) и с виндовым реестром можно работать (nsIWindowsRegKey), и приложения запускать (nsIProcess), но… Как-то не хочется с этим возиться.

Categories: PHP | comments: (9)

Комментарии

1. Ilya Birman 22nd October 2005 - 16:39

Хоть я и пользуюсь аутлуком, но прочитал с интересом, надо будет взять на заметку вообще, что есть WSH под рукой… Спасибо :-)

P.S. Почему-то у тебя «Categories: PHP», поправь?

Mash:

Да не за что. :)

Менять категории после поста этот движок не позволяет; надо дописывать, а мне лень. Anyway, это не ошибка, т.к. «программист, ага».

2. Ilya Birman 22nd October 2005 - 16:52

Ставь e2! :-) Скоро выйдет новый релиз :-)

Mash:

Я всё никак скачать/посмотреть не могу, а ты говоришь «Ставь» :). Движок-то меня и свой устраивает по большей части, но есть такие вот моменты, как с категориями, да.

Update: +. Это мой пунктик. Знаю, что жизненной необходимости нет, но всё равно менять MIME-Type не собираюсь.

3. Ilya Birman 22nd October 2005 - 17:41

Насчёт XHTML — я бы с удовольствием добился того же в e2, только это, наверное, трудно? И вопрос ещё в том, как бороться с user-defined дизайном, а также с разметкой оставляемой в заметках/комментариях — как добиться того, чтобы вики-парсер выдавал правильный XHTML?

Ну-ка, <a href=http://quote-every-attribute.org>постестим-ка</A> твой движок… :-) (можешь удалить эту строчку)

4. Ilya Birman 22nd October 2005 - 17:42

Ага, ну то есть видишь, у тебя получается, что ты и сам с пунктиком, и других заставляешь, хотя если уж быть фриком до конца, то можно автоматизировать. Поэтому я пока предпочёл просто забить.

Mash:

>> …как бороться с user-defined дизайном…

Вынести это в настройки движка, где отключить по-умолчанию. Кому надо — включат.

Заметки/комментарии, вики-парсер… У меня всё сделано «на коленке» и это хозяйство достаточно легко завалить, но, насколько мне известно, если задаться этим вопросом, то можно что-нибудь дельное придумать. Вон, к примеру, у kukutz’а в SafeHTML вроде как обещана выдача валидного XHTML ([освежив в памяти] хотя нет, только «tries to convert»). Может быть ещё чего на эту тему можно в сети наковырять,.. не знаю. Всё это достижимо™, но если нет острой необходимости (а её у тебя нет), то лучше действительно забить, потому как хостеры часто не дают всего того, при помощи чего это достигалось бы меньшими танцами с бубном. Взять тот же tidy.

Я не заставляю, просто вспомнилось. :)

5. Ilya Birman 22nd October 2005 - 19:04

Я понял что не заставляешь, я просто хотел сказать, что стремление ко всему правильному мне очень понятно и совсем не чуждо :)

6. Julik 24th October 2005 - 09:15

c MIME-типом XHTML перестают работать Некоторые Вещи. Например такая мелкая ненужная DOMNode.innerHTML.

Mash:

innerHTML — редкостная гадость (пример) просто потому, что нет никаких стандартов на это дело. Но вещь жутко удобная и быстрая, да.

Для меня XHTML — это прежде всего культура. Ну не могу я посылать мусор, передёргивает. :) Иначе можно докатиться до того, что и работа обычных вещей будет ставить в тупик.

Если вдруг мне когда-нибудь понадобится тот же самый innerHTML и ситуация будет такой, что различные workaround (aka танцы с бубном) будут выглядеть тошнотворно по сравнению с отказом от XHTML, то я с лёгкостью откачусь на HTML. Я не упёртый фанатик, во мне есть пара-тройка капель разума, которые заставляют согласиться, что лучше пусть будут маленькие и шустрые «некоторые вещи», чем неповоротливые костыли. Пока же таких ситуаций не было.

Кстати, в Fx innerHTML при определённых условиях таки работает. Да и баг есть, который хоть и с 2002 года, но всё-таки народ там ковыряется потихоньку. А как там дела у Safari в этом плане; всё так же?

7. Julik 24th October 2005 - 22:38

Я в данный момент юзаю Prototype у которого как минимум яксовый движок построен именно на InnerHTML (то есть на возвращении сервером готовых _фрагментов_ страницы — который по ряду причин удобнее чем заливка данных в уже загруженный хтмл). Более того, ты же сам писал недавно — что у файрфокса нового появилась функция 1 в 1 повторяющая innerHTML, но только для XML. А смысл? (Кроме того что W3C нарочно не предусмотрел вставку сериализованного фрагмента в DOM-дерево, и для этого нету ни одного понятного объяснения).
Дела так-же.

Mash:

>> Более того, ты же сам писал недавно — что у файрфокса нового появилась функция 1 в 1 повторяющая innerHTML, но только для XML.

В новом фоксе и innerHTML работает (первая ссылка в последнем абзаце моего предыдущего ответа).

Я тут побаловался немного. :)

8. GregoryPek 14th November 2005 - 11:21

Здравствуйте, у меня как у «чайника» вопросы по« WSH: Thunderbird, dialing, get mail, disconnect»:
1. Как правильно запустить?
Стоит WinXP SP2 RUS, Thunderbird 1.0.7 (ru)

Я делал так, скопировал все «шаги1-4» в текстовый редактор, присвоил файлу расширение .VBS. Запускаю, ошибка. С 1-й же строки последнего символа. Вот мой файл:

Mash:

Я удалил тот код, который был вами написан. Скачайте файл autoDilaUp.wsf, сохраните его на диск и запустите. Прошу прощения за то, что до этого ссылка на файл была «битой».

Два замечания:

  • для корректной работы необходимо модемное соединение, выставленное по-умолчанию таким образом, что оно не запрашивает логин/пароль при дозвонке;
  • для WinRU скорее всего придётся сделать некоторые изменения. Откройте консоль («Пуск»->«Командная строка» или как там это в русской версии называется,.. не помню точно), наберите "rasdial" и посмотрите что выведет эта команда. В английской версии первой строкой идёт «No connections» (см. «Шаг 2» в заметке). Нужно будет открыть файл autoDilaUp.wsf и в 36-ой строке заменить «No connections» на то, что получится у вас.
9. GregoryPek 15th November 2005 - 08:23

Благодарю за ответ, скачал, исправил как сказали, но выдает ошибку:
«Строка: 32, Символ:3, Ошибка:Не удается найти указанный файл.»

Вопро «чайника», есть в WinXP какой нибудь отладчик для WSH?

Mash:

Давайте пойдём в почту разбираться с русским XP, ладно? Сейчас напишу письмо.

>> есть в WinXP какой нибудь отладчик для WSH?

Честно говоря, не интересовался.

Комментарии временно отключены.