I really needed to know who were email recipients. There are several good reasons for this and I just had one of those. So it was time to do some experimenting!
Write this (thrice now), which is close, but just not good enough. Maybe someone can continue from here? First standard didFinishWithResult callback, nothing special there. Bit simplified for this case:
- (void)mailComposeController:(MFMailComposeViewController *)controllerHere's the interesting code, which can be used to peek what's inside the MFMailComposeViewController blackbox (UPDATE: easier way to check view hierarchy). Pretty common view hierarchy walking code, now especially looking for text strings:
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error
{
if (result == MFMailComposeResultSent)
{
NSString *email = [self findEmailAddresses:controller.view depth:0];
NSLog(@"%@", email);
[self.viewController dismissModalViewControllerAnimated:YES];
}
}
- (NSString *)findEmailAddresses:(UIView *)view depth:(NSInteger)countProblems: it finds the recipient email address(es), but only if that fits in about 35 character text string. Otherwise you find only a summary string like "aaa@aaa.aa & 2 more...". So where are the actual email addresses in this case?
{
NSString *eAddress = nil;
if (!view)
return eAddress;
NSMutableString *tabString = [NSMutableString stringWithCapacity:depth];
for (int i = 0; i < depth; i++)
[tabString appendString:@"-- "];
NSLog(@"%@%@", tabString, view);
if ([view isKindOfClass:[UITextField class]])
{
// MAGIC: debugger shows email address(es) in first textField
// but only if it's about max 35 characters
if (((UITextField *)view).text)
{
eAddress = [NSString stringWithString:((UITextField *)view).text];
NSLog(@"FOUND UITextField: %@", eAddress ? eAddress : @"");
}
}
NSArray *subviews = [view subviews];
if (subviews) {
for (UIView *view in subviews)
{
NSString *s = [self findEmailAddresses:view depth:depth+1];
if (s) eAddress = s;
}
}
return eAddress;
}
Great post. I'm dealing with the same thing right now. I was just recursively going through all the subviews until I found the MFRecipientTextField view... but that leads to the same "& 2 more..." problem. Did you find a way to get this to work?
ReplyDeleteAlso, I don't quite understand what your code is doing. Is "depth" only needed for debugging purposes, or is it actually needed for you to find the email address? I'm doing basically the same thing, but I'm never using appendString or depth. Thanks!
Nope, I gave up. We thought that getting email recipient addresses this way might get app rejected, so code was never used for real. But I'm still interested, in case you solve the "& 2 more..." :)
ReplyDeleteDepth is used to make debug output more readable, nothing else.
I am sending email using default mailComposer using MFMailComposerViewController. I don't know how to set the from email address and where to set its credentials....Can anyone help me out please
ReplyDeleteThat info comes from your Mail settings. Can't change them in code by yourself.
ReplyDeleteCan we just get From Email address.. I dont want to change that address
ReplyDeleteFrom Email address depends on user's Mail settings, don't know how to get it. Why would you even need it ar client side, I'm wondering.. Anyway, once your server receives the email, then you know it :)
ReplyDeleteHey Jouni did u got the solution of the above said problem, am in need to know the no. of email adresses the user has entered. Pls do update if u got any solution for the same
ReplyDeleteSorry, but no. Still no idea where to find the "remaining" email addresses.
ReplyDeleteHey thanks for the Quick reply, I am using ur code in my App is there any chance that Apple reviewers may catch me accessing their private APis, if yes please do reply me.
DeleteThanks n Regards
Will Apple catch you using private APIs: YES! They have automated tools to do such things :)
ReplyDeleteHowever going through object hierarchy is not using any private APIs, so it depends on app UI. If you make it obvious that you're doing something which shouldn't be done, you risk rejection.
Hi Juoni, this is a great site and tutorial.
ReplyDeleteI am preparing an application where i will accept member users. I want to verify the email of signing user. To do so, i want to send an activasion code to the user and write this code and mail adress matching into sqlite database. After as user checks the mail account and write the activasion code i want to accept as user. This way i will be sure that this mail adress is real and the guy who wants to sign in is the real user.
How to let user take an activasion code to his/her mail adress??? This mail will be generated automatically and will be sent from one source.
Please share your ideas cuz could not find any tutorial.
Easy: you request user email address and send that internally to your server. Server sends the account verification email containing an URL pointing back to your server. That URL contains same (or rather some other unique code generated from original) activation code as parameter :)
ReplyDeleteIn other words, client does not send the email. To create a client-server system without a server would be... interesting. Lot of challenges.