#!/usr/bin/perl # # The script uses SOAP (SOAP is not "simple"!) to access data # stored at FastMail.FM. The SOAP::MessaginEngine module can be # found at: # # http://wiki.fastmail.fm/index.php?title=FastServicesPerl # # Copyright (c) by Kirill Miazine # # This software is distributed under an ISC-style license, please see # for details. # use feature qw(:5.10); use strict; use warnings; use SOAP::MessagingEngine; import SOAP::Data qw(name value); use JSON; use IO::All; use Date::Parse; use Encode qw(decode_utf8); # FastMail username my $user = 'km@krot.org'; # FastMail password (put password in ~/.fmpw or enter it here) my $pass = io("$ENV{'HOME'}/.fmpw")->chomp->getline; my $sess = SOAP::MessagingEngine->new('https://www.fastmail.fm/SOAP/', $user, $pass) or exit; my ($table, $fields, $crit, $rows); # # abook # # 0 1 2 3 4 my @types = qw(Email HomePhone WorkPhone MobilePhone OtherPhone Fax Web Other Pager IM Chat); # 5 6 7 8 9 10 # contacts (aka. addresses) $table = name(Table => 'Addresses'); $fields = name( FieldList => value([map { name(Field => $_) } qw(AddressId LastUpdate NickName Notes Title FirstName SurName Birthday Position Company Department)]) ); $rows = $sess->Database_Select($table, $fields) // []; my %abook; for (@{$rows}) { my ($id, $updated, $nick, $notes, $title, $first, $last, $bday, $pos, $comp, $dept) = map { decode_utf8($_) } @{$_}; my $name = $last ? "$first $last" : $first; $name =~ s/(^\s*|\s*$)//; my $name2 = $last ? "$last, $first" : $first; $name2 =~ s/(^\s*|\s*$)//; $updated = int(str2time($updated) + 21600); $abook{$id} = { id => $id, updated => $updated, notes => $notes, birthday => $bday, name => $name, first => $first, last => $last, nickname => $nick, revname => $name2, position => $pos, company => $comp, department => $dept, groups => [], entries => [], }; } # entries (aka. contacts) $table = name(Table => 'Contacts'); $fields = name( FieldList => value([map { name(Field => $_) } qw(AddressId ContactId ContactType Details Notes)]) ); $rows = $sess->Database_Select($table, $fields) // []; for (sort { $a->[1] <=> $b->[1] } @{$rows}) { my ($id, $cid, $type, $details, $notes) = map { decode_utf8($_) } @{$_}; next if !exists $abook{$id}; my $x = $abook{$id}; push @{$x->{'entries'}}, [$details, $types[$type]]; } # groups $table = name(Table => 'Groups'); $fields = name( FieldList => value([name(Field => 'GroupId'), name(Field => 'DisplayName')]) ); $rows = $sess->Database_Select($table, $fields) // []; my %groups = map { $_->[0] => decode_utf8($_->[1]) } @{$rows}; $table = name(Table => 'GroupAddrs'); $fields = name( FieldList => value([name(Field => 'GroupId'), name(Field => 'AddressId')]) ); $rows = $sess->Database_Select($table, $fields) // []; for (@{$rows}) { my ($gid, $aid) = @{$_}; next if !exists $abook{$aid}; push @{$abook{$aid}->{'groups'}}, $groups{$gid}; } say to_json([sort { $a->{'name'} cmp $b->{'name'} } values %abook], {utf8 => 1, pretty => 1}); $sess->Logout();