I'm not aware of an App Exchange App for it, but someone else might be.
You should be able to use the Data Loader, but the only catch would be that the new user email notification would not go out.
If you use Apex from a custom page, batch job, or just execute anonymous you have to set the DMLOptions to send email if you want email to be sent, for example:
List<Contact> portalContacts = [
Select Id, ...
From Contact
Where ...
];
Id portalProfileId = '123456789012345678';
Boolean sendUserEmail = true;
Boolean allOrNone = true;
List<User> newUsers = new List<User>();
for (Contact contact : portalContacts) {
String alias = contact.LastName;
if (alias.length() > 8) {
alias = alias.substring(0, 8);
}
String nickName = contact.Email;
if (nickName.length() > 40) {
nickName = nickName.substring(0, 40);
}
User newUser = new User(
UserName = contact.Email,
LastName = contact.LastName,
FirstName = contact.FirstName,
Email = contact.Email,
phone = contact.Phone,
MobilePhone = contact.MobilePhone,
Street = contact.MailingStreet,
City = contact.MailingCity,
State = contact.MailingState,
Country = contact.MailingCountry,
PostalCode = contact.MailingPostalCode,
CommunityNickName = nickName,
Alias = alias,
/* link to the contact and to the account through the contact... */
ContactId = contact.Id,
ProfileId = portalProfileId,
/* various user settings */
emailencodingkey = 'UTF-8',
languagelocalekey = 'en_US',
localesidkey = 'en_US',
timezonesidkey = 'America/Los_Angeles'
);
Database.DMLOptions dmo = new Database.DMLOptions();
dmo.EmailHeader.triggerUserEmail = sendUserEmail;
newUser.setOptions(dmo);
newUsers.add(newUser);
}
if (!newUsers.isEmpty()) {
Database.SaveResult[] results = Database.insert(newUsers, allOrNone);
// any post processing...
}