Search code examples
objective-ciosmacosemailmime

Mime Encoded-Word parsing in Objective-C


Do OS X or iOS provide an API to parse MIME Encoded-Word? These lovely strings:

=?iso-8859-1?Q?=A1Hola,_se=F1or!?=

Alternatively, is there a known open-source library that does this?


Solution

  • I took @NickolayO.'s answer, added base-64 support with QSStrings and shortened the code by using componentsSeparatedByString: and stringByReplacingOccurrencesOfString:withString:.

    I've made the code available on GitHub. Here's a snippet for convenience:

    @implementation NSString (MimeEncodedWord)
    
    - (BOOL) isMimeEncodedWord
    {
        return [self hasPrefix:@"=?"]  && [self hasSuffix:@"?="];
    }
    
    + (NSString*) stringWithMimeEncodedWord:(NSString*)word
    { // Example: =?iso-8859-1?Q?=A1Hola,_se=F1or!?=
        NSArray *components = [word componentsSeparatedByString:@"?"];
        if (components.count < 5) return nil;
    
        NSString *charset = [components objectAtIndex:1];
        NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((CFStringRef)charset)); // TODO: What happens if the encoding is invalid?
    
        NSString *encodingType = [components objectAtIndex:2];
        NSString *encodedText = [components objectAtIndex:3];
        if ([encodingType isEqualToString:@"Q"])
        { // quoted-printable
            encodedText = [encodedText stringByReplacingOccurrencesOfString:@"_" withString:@" "];
            encodedText = [encodedText stringByReplacingOccurrencesOfString:@"=" withString:@"%"];
            NSString *decoded = [encodedText stringByReplacingPercentEscapesUsingEncoding:encoding];
            return decoded;
        } else if ([encodingType isEqualToString:@"B"])
        { // base64
            NSData *data = [QSStrings decodeBase64WithString:encodedText];
            NSString *decoded = [[NSString alloc] initWithData:data encoding:encoding];
            return decoded;
        } else {
            NSLog(@"%@ is not a valid encoding (must be Q or B)", encodingType);
            return nil;
        }    
    }
    
    @end