You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@nifi.apache.org by trixpan <gi...@git.apache.org> on 2016/08/09 12:09:53 UTC

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

GitHub user trixpan opened a pull request:

    https://github.com/apache/nifi/pull/817

    NIFI-2380 - Introduce ExtractTNEFAttachments

    a processor to extract attachments embedded within a Transport Neutral Encapsulation Format (TNEF) attachment (i.e. winmail.dat)

You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/trixpan/nifi NIFI-2380

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/nifi/pull/817.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #817
    
----
commit 8794ee721ec1d44f592d7f8a752a92604cb35386
Author: Andre F de Miranda <tr...@users.noreply.github.com>
Date:   2016-08-09T12:08:26Z

    NIFI-2380 - Introduce ExtractTNEFAttachment - A processor to extract
    attachments embedded within a Transport Neutral Encapsulation Format (TNEF) attachment (i.e. winmail.dat)

----


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77625666
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    --- End diff --
    
    addressed


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @olegz I guess you have been busy but I was wondering if you are still planning to review this? 
    
    Cheers


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @olegz how is testing looking like?
    
    Cheers


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @olegz 
    
    Rebased.
    
    Please note that while I will be happy to keep rebasing as peer review is in progress, this PR makes additions to the nifi-assembly LICENSE and NOTICE files so it is expected it will continue experience merge conflicts, as other PRs try to change the same file.
    
    Cheers


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @olegz ?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @olegz hopefully all comments addressed. Code was rebased as well


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by olegz <gi...@git.apache.org>.
Github user olegz commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    Ok, will take a look and run through tests


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77625649
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    +            .build();
    +    public static final Relationship REL_FAILURE = new Relationship.Builder()
    +            .name("failure")
    +            .description("Flowfiles that could not be parsed")
    +            .build();
    +    private Set<Relationship> relationships;
    +    private List<PropertyDescriptor> descriptors;
    +
    +
    +    @Override
    +    protected void init(final ProcessorInitializationContext context) {
    +        final Set<Relationship> relationships = new HashSet<>();
    +        relationships.add(REL_ATTACHMENTS);
    +        relationships.add(REL_ORIGINAL);
    +        relationships.add(REL_FAILURE);
    +        this.relationships = Collections.unmodifiableSet(relationships);
    +
    +        final List<PropertyDescriptor> descriptors = new ArrayList<>();
    +
    +        this.descriptors = Collections.unmodifiableList(descriptors);
    +    }
    --- End diff --
    
    Addressed


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @joewitt 
    
    I will need some assistance with the L&N issue:
    
    Note how POIs LICENSE makes mention to CurvesAPI
    https://github.com/apache/poi/blob/trunk/legal/LICENSE#L459
    
    Looking at CurvesAPI, the authors seem to require notice
    https://github.com/virtuald/curvesapi/blob/master/license.txt#L8
    
    However POIs NOTICE does not make mention to CurvesAPI
    https://github.com/apache/poi/blob/trunk/legal/NOTICE#L5
    
    Is NOTICE required (despite POI lacking it) or can we address that by appending nifi-assembly and the nar LICENSE files with: 
    
    ```
    This project bundles 'CurvesAPI' which is available under a BSD license.
    
        Copyright (c) 2005, Graph Builder
        All rights reserved.
        
        Redistribution and use in source and binary forms, with or without
        modification, are permitted provided that the following conditions
        are met:
        
        -Redistributions of source code must retain the above copyright notice,
        this list of conditions and the following disclaimer.
        
        -Redistributions in binary form must reproduce the above copyright notice,
        this list of conditions and the following disclaimer in the documentation
        and/or other materials provided with the distribution.
        
        -Neither the name of Graph Builder nor the names of its contributors may be
        used to endorse or promote products derived from this software without
        specific prior written permission.
        
        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    ```


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77625743
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    +            .build();
    +    public static final Relationship REL_FAILURE = new Relationship.Builder()
    +            .name("failure")
    +            .description("Flowfiles that could not be parsed")
    +            .build();
    +    private Set<Relationship> relationships;
    +    private List<PropertyDescriptor> descriptors;
    +
    +
    +    @Override
    +    protected void init(final ProcessorInitializationContext context) {
    +        final Set<Relationship> relationships = new HashSet<>();
    +        relationships.add(REL_ATTACHMENTS);
    +        relationships.add(REL_ORIGINAL);
    +        relationships.add(REL_FAILURE);
    +        this.relationships = Collections.unmodifiableSet(relationships);
    +
    +        final List<PropertyDescriptor> descriptors = new ArrayList<>();
    +
    +        this.descriptors = Collections.unmodifiableList(descriptors);
    +    }
    +
    +    @Override
    +    public void onTrigger(final ProcessContext context, final ProcessSession session) {
    +        final ComponentLog logger = getLogger();
    +        final FlowFile originalFlowFile = session.get();
    +        if (originalFlowFile == null) {
    +            return;
    +        }
    +        final List<FlowFile> attachmentsList = new ArrayList<>();
    +        final List<FlowFile> invalidFlowFilesList = new ArrayList<>();
    +        final List<FlowFile> originalFlowFilesList = new ArrayList<>();
    +
    +        session.read(originalFlowFile, new InputStreamCallback() {
    +                @Override
    +                public void process(final InputStream rawIn) throws IOException {
    +                    try (final InputStream in = new BufferedInputStream(rawIn)) {
    +                        Properties props = new Properties();
    +
    +                        HMEFMessage hmefMessage = null;
    +
    +                            // This will trigger an exception in case content is not a TNEF.
    +                            hmefMessage = new HMEFMessage(in);
    +
    --- End diff --
    
    addressed.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @olegz 
    
    Would you mind have a look on this PR ?
    
    Function here is to extract TNEF attachments. TNEF is the technical name for the widely loved winmail.dat files.
    
    Use case is:
    
    SMPT/POP -> ExtractAttachments > Route based on mime.type -> ExtractTNEF -> whatever


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by olegz <gi...@git.apache.org>.
Github user olegz commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77615322
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    +            .build();
    +    public static final Relationship REL_FAILURE = new Relationship.Builder()
    +            .name("failure")
    +            .description("Flowfiles that could not be parsed")
    +            .build();
    +    private Set<Relationship> relationships;
    +    private List<PropertyDescriptor> descriptors;
    +
    +
    +    @Override
    +    protected void init(final ProcessorInitializationContext context) {
    +        final Set<Relationship> relationships = new HashSet<>();
    +        relationships.add(REL_ATTACHMENTS);
    +        relationships.add(REL_ORIGINAL);
    +        relationships.add(REL_FAILURE);
    +        this.relationships = Collections.unmodifiableSet(relationships);
    +
    +        final List<PropertyDescriptor> descriptors = new ArrayList<>();
    +
    +        this.descriptors = Collections.unmodifiableList(descriptors);
    +    }
    +
    +    @Override
    +    public void onTrigger(final ProcessContext context, final ProcessSession session) {
    +        final ComponentLog logger = getLogger();
    +        final FlowFile originalFlowFile = session.get();
    +        if (originalFlowFile == null) {
    +            return;
    +        }
    +        final List<FlowFile> attachmentsList = new ArrayList<>();
    +        final List<FlowFile> invalidFlowFilesList = new ArrayList<>();
    +        final List<FlowFile> originalFlowFilesList = new ArrayList<>();
    +
    +        session.read(originalFlowFile, new InputStreamCallback() {
    +                @Override
    +                public void process(final InputStream rawIn) throws IOException {
    +                    try (final InputStream in = new BufferedInputStream(rawIn)) {
    +                        Properties props = new Properties();
    +
    +                        HMEFMessage hmefMessage = null;
    +
    +                            // This will trigger an exception in case content is not a TNEF.
    +                            hmefMessage = new HMEFMessage(in);
    +
    +                        // Add otiginal flowfile (may revert later on in case of errors) //
    +                        originalFlowFilesList.add(originalFlowFile);
    +
    +                        if (hmefMessage != null) {
    +                             // Attachments isn empty, proceeding.
    +                            if (! hmefMessage.getAttachments().isEmpty()) {
    +                                final String originalFlowFileName = originalFlowFile.getAttribute(CoreAttributes.FILENAME.key());
    +                                try {
    +                                    for (final Attachment attachment : hmefMessage.getAttachments()) {
    +                                        FlowFile split = session.create(originalFlowFile);
    +                                        final Map<String, String> attributes = new HashMap<>();
    +                                        if (StringUtils.isNotBlank(attachment.getLongFilename())) {
    +                                            attributes.put(CoreAttributes.FILENAME.key(), attachment.getFilename());
    +                                        }
    +
    +                                        String parentUuid = originalFlowFile.getAttribute(CoreAttributes.UUID.key());
    +                                        attributes.put(ATTACHMENT_ORIGINAL_UUID, parentUuid);
    +                                        attributes.put(ATTACHMENT_ORIGINAL_FILENAME, originalFlowFileName);
    +
    +                                        // TODO: Extract Mime Type (HMEF doesn't seem to be able to get this info.
    +
    +                                        split = session.append(split, new OutputStreamCallback() {
    +                                            @Override
    +                                            public void process(OutputStream out) throws IOException {
    +                                                out.write(attachment.getContents());
    +                                            }
    +                                        });
    +                                        split = session.putAllAttributes(split, attributes);
    +                                        attachmentsList.add(split);
    +                                    }
    +                                } catch (FlowFileHandlingException e) {
    +                                    // Something went wrong
    +                                    // Removing splits that may have been created
    +                                    session.remove(attachmentsList);
    +                                    // Removing the original flow from its list
    +                                    originalFlowFilesList.remove(originalFlowFile);
    +                                    logger.error("Flowfile {} triggered error {} while processing message removing generated FlowFiles from sessions", new Object[]{originalFlowFile, e});
    +                                    invalidFlowFilesList.add(originalFlowFile);
    +                                }
    +                            }
    +                        }
    +                    }catch (Exception e) {
    +                        // Another error hit...
    +                        // Removing the original flow from its list
    +                        originalFlowFilesList.remove(originalFlowFile);
    +                        logger.error("Could not parse the flowfile {} as an email, treating as failure", new Object[]{originalFlowFile, e});
    +                        // Message is invalid or triggered an error during parsing
    +                        invalidFlowFilesList.add(originalFlowFile);
    +                    }
    +                }
    +        });
    +
    +        session.transfer(attachmentsList, REL_ATTACHMENTS);
    +
    +        // As per above code, originalFlowfile may be routed to invalid or
    +        // original depending on RFC2822 compliance.
    +        session.transfer(invalidFlowFilesList, REL_FAILURE);
    +        session.transfer(originalFlowFilesList, REL_ORIGINAL);
    +
    +        if (attachmentsList.size() > 10) {
    +            logger.info("Split {} into {} files", new Object[]{originalFlowFile, attachmentsList.size()});
    +        } else if (attachmentsList.size() > 1){
    +            logger.info("Split {} into {} files: {}", new Object[]{originalFlowFile, attachmentsList.size(), attachmentsList});
    +        }
    --- End diff --
    
    I am not sure I understand this IF block. It appears you want to display the 'attachmentsList' if it's size is > 1, but you don't want to display it when it is > 10 which is also > 1. Could you please clarify?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by olegz <gi...@git.apache.org>.
Github user olegz commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77614060
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    --- End diff --
    
    I would use the same style that you used in _ attachments_ relationship description _". . . will be routed to. . .". The way it is now may be a bit confusing.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by joewitt <gi...@git.apache.org>.
Github user joewitt commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    Hello.  The POI-Scratchpad dependency version being referenced as 'RELEASE' does not look correct.  It appears the latest release version of poi-scratchpad is 3.14.  Also, the PR needs to be updated to reflect the necessary L&N considers for the nar and the nifi-assembly as these will be pulling in dependencies.  I don't know if poi-scratchpad is the only jar or if it pulls others but that will need to be accounted for.  Quick check of the NOTICE for poi shows we will need to propogate some elements into our nifi-assembly/NOTICe and a NOTICE within the nar itself as well.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by olegz <gi...@git.apache.org>.
Github user olegz commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77613540
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    +            .build();
    +    public static final Relationship REL_FAILURE = new Relationship.Builder()
    +            .name("failure")
    +            .description("Flowfiles that could not be parsed")
    +            .build();
    +    private Set<Relationship> relationships;
    +    private List<PropertyDescriptor> descriptors;
    +
    +
    +    @Override
    +    protected void init(final ProcessorInitializationContext context) {
    +        final Set<Relationship> relationships = new HashSet<>();
    +        relationships.add(REL_ATTACHMENTS);
    +        relationships.add(REL_ORIGINAL);
    +        relationships.add(REL_FAILURE);
    +        this.relationships = Collections.unmodifiableSet(relationships);
    +
    +        final List<PropertyDescriptor> descriptors = new ArrayList<>();
    +
    +        this.descriptors = Collections.unmodifiableList(descriptors);
    +    }
    --- End diff --
    
    I know it's kind of a pattern in some old processors, but we also discovered the issue with it since _init()_ method as well as few others are invoked more then once per life-cycle of a processor (see https://issues.apache.org/jira/browse/NIFI-1318), so instead consider static initializer (see ListenSMTP for example)


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @JPercivall - Given your review of ExtractEmailAttachments do you mind reviewing this PR? Cheers


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by olegz <gi...@git.apache.org>.
Github user olegz commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77614809
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    +            .build();
    +    public static final Relationship REL_FAILURE = new Relationship.Builder()
    +            .name("failure")
    +            .description("Flowfiles that could not be parsed")
    +            .build();
    +    private Set<Relationship> relationships;
    +    private List<PropertyDescriptor> descriptors;
    +
    +
    +    @Override
    +    protected void init(final ProcessorInitializationContext context) {
    +        final Set<Relationship> relationships = new HashSet<>();
    +        relationships.add(REL_ATTACHMENTS);
    +        relationships.add(REL_ORIGINAL);
    +        relationships.add(REL_FAILURE);
    +        this.relationships = Collections.unmodifiableSet(relationships);
    +
    +        final List<PropertyDescriptor> descriptors = new ArrayList<>();
    +
    +        this.descriptors = Collections.unmodifiableList(descriptors);
    +    }
    +
    +    @Override
    +    public void onTrigger(final ProcessContext context, final ProcessSession session) {
    +        final ComponentLog logger = getLogger();
    +        final FlowFile originalFlowFile = session.get();
    +        if (originalFlowFile == null) {
    +            return;
    +        }
    +        final List<FlowFile> attachmentsList = new ArrayList<>();
    +        final List<FlowFile> invalidFlowFilesList = new ArrayList<>();
    +        final List<FlowFile> originalFlowFilesList = new ArrayList<>();
    +
    +        session.read(originalFlowFile, new InputStreamCallback() {
    +                @Override
    +                public void process(final InputStream rawIn) throws IOException {
    +                    try (final InputStream in = new BufferedInputStream(rawIn)) {
    +                        Properties props = new Properties();
    +
    +                        HMEFMessage hmefMessage = null;
    +
    +                            // This will trigger an exception in case content is not a TNEF.
    +                            hmefMessage = new HMEFMessage(in);
    +
    --- End diff --
    
    Not a big deal, but there seem to be formatting/indentation/style issues which makes it a bit difficult to review. Not a big deal since it could be fixed during the merge, but I was wondering if we can help to set you up in such way where you style match the rest of the NiFi. Have you look at this- https://cwiki.apache.org/confluence/display/NIFI/Contributor+Guide#ContributorGuide-CodeStyle. In any event let me know if you have any troubles and we can definitely help. 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on a diff in the pull request:

    https://github.com/apache/nifi/pull/817#discussion_r77626391
  
    --- Diff: nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/java/org/apache/nifi/processors/email/ExtractTNEFAttachments.java ---
    @@ -0,0 +1,202 @@
    +/*
    + * Licensed to the Apache Software Foundation (ASF) under one or more
    + * contributor license agreements.  See the NOTICE file distributed with
    + * this work for additional information regarding copyright ownership.
    + * The ASF licenses this file to You under the Apache License, Version 2.0
    + * (the "License"); you may not use this file except in compliance with
    + * the License.  You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package org.apache.nifi.processors.email;
    +
    +import org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.annotation.behavior.EventDriven;
    +import org.apache.nifi.annotation.behavior.InputRequirement;
    +import org.apache.nifi.annotation.behavior.InputRequirement.Requirement;
    +import org.apache.nifi.annotation.behavior.SideEffectFree;
    +import org.apache.nifi.annotation.behavior.SupportsBatching;
    +import org.apache.nifi.annotation.behavior.WritesAttribute;
    +import org.apache.nifi.annotation.behavior.WritesAttributes;
    +import org.apache.nifi.annotation.documentation.CapabilityDescription;
    +import org.apache.nifi.annotation.documentation.Tags;
    +import org.apache.nifi.components.PropertyDescriptor;
    +import org.apache.nifi.flowfile.FlowFile;
    +import org.apache.nifi.flowfile.attributes.CoreAttributes;
    +import org.apache.nifi.logging.ComponentLog;
    +import org.apache.nifi.processor.AbstractProcessor;
    +import org.apache.nifi.processor.ProcessContext;
    +import org.apache.nifi.processor.ProcessSession;
    +import org.apache.nifi.processor.ProcessorInitializationContext;
    +import org.apache.nifi.processor.Relationship;
    +import org.apache.nifi.processor.exception.FlowFileHandlingException;
    +import org.apache.nifi.processor.io.InputStreamCallback;
    +import org.apache.nifi.processor.io.OutputStreamCallback;
    +import org.apache.nifi.stream.io.BufferedInputStream;
    +import org.apache.poi.hmef.Attachment;
    +import org.apache.poi.hmef.HMEFMessage;
    +
    +import java.io.IOException;
    +import java.io.InputStream;
    +import java.io.OutputStream;
    +import java.util.ArrayList;
    +import java.util.Collections;
    +import java.util.HashMap;
    +import java.util.HashSet;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.Properties;
    +import java.util.Set;
    +
    +
    +@SupportsBatching
    +@EventDriven
    +@SideEffectFree
    +@Tags({"split", "email"})
    +@InputRequirement(Requirement.INPUT_REQUIRED)
    +@CapabilityDescription("Extract attachments from a mime formatted email file, splitting them into individual flowfiles.")
    +@WritesAttributes({
    +        @WritesAttribute(attribute = "filename ", description = "The filename of the attachment"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.filename ", description = "The filename of the parent FlowFile"),
    +        @WritesAttribute(attribute = "email.tnef.attachment.parent.uuid", description = "The UUID of the original FlowFile.")})
    +
    +public class ExtractTNEFAttachments extends AbstractProcessor {
    +    public static final String ATTACHMENT_ORIGINAL_FILENAME = "email.tnef.attachment.parent.filename";
    +    public static final String ATTACHMENT_ORIGINAL_UUID = "email.tnef.attachment.parent.uuid";
    +
    +    public static final Relationship REL_ATTACHMENTS = new Relationship.Builder()
    +            .name("attachments")
    +            .description("Each individual attachment will be routed to the attachments relationship")
    +            .build();
    +    public static final Relationship REL_ORIGINAL = new Relationship.Builder()
    +            .name("original")
    +            .description("The original file")
    +            .build();
    +    public static final Relationship REL_FAILURE = new Relationship.Builder()
    +            .name("failure")
    +            .description("Flowfiles that could not be parsed")
    +            .build();
    +    private Set<Relationship> relationships;
    +    private List<PropertyDescriptor> descriptors;
    +
    +
    +    @Override
    +    protected void init(final ProcessorInitializationContext context) {
    +        final Set<Relationship> relationships = new HashSet<>();
    +        relationships.add(REL_ATTACHMENTS);
    +        relationships.add(REL_ORIGINAL);
    +        relationships.add(REL_FAILURE);
    +        this.relationships = Collections.unmodifiableSet(relationships);
    +
    +        final List<PropertyDescriptor> descriptors = new ArrayList<>();
    +
    +        this.descriptors = Collections.unmodifiableList(descriptors);
    +    }
    +
    +    @Override
    +    public void onTrigger(final ProcessContext context, final ProcessSession session) {
    +        final ComponentLog logger = getLogger();
    +        final FlowFile originalFlowFile = session.get();
    +        if (originalFlowFile == null) {
    +            return;
    +        }
    +        final List<FlowFile> attachmentsList = new ArrayList<>();
    +        final List<FlowFile> invalidFlowFilesList = new ArrayList<>();
    +        final List<FlowFile> originalFlowFilesList = new ArrayList<>();
    +
    +        session.read(originalFlowFile, new InputStreamCallback() {
    +                @Override
    +                public void process(final InputStream rawIn) throws IOException {
    +                    try (final InputStream in = new BufferedInputStream(rawIn)) {
    +                        Properties props = new Properties();
    +
    +                        HMEFMessage hmefMessage = null;
    +
    +                            // This will trigger an exception in case content is not a TNEF.
    +                            hmefMessage = new HMEFMessage(in);
    +
    +                        // Add otiginal flowfile (may revert later on in case of errors) //
    +                        originalFlowFilesList.add(originalFlowFile);
    +
    +                        if (hmefMessage != null) {
    +                             // Attachments isn empty, proceeding.
    +                            if (! hmefMessage.getAttachments().isEmpty()) {
    +                                final String originalFlowFileName = originalFlowFile.getAttribute(CoreAttributes.FILENAME.key());
    +                                try {
    +                                    for (final Attachment attachment : hmefMessage.getAttachments()) {
    +                                        FlowFile split = session.create(originalFlowFile);
    +                                        final Map<String, String> attributes = new HashMap<>();
    +                                        if (StringUtils.isNotBlank(attachment.getLongFilename())) {
    +                                            attributes.put(CoreAttributes.FILENAME.key(), attachment.getFilename());
    +                                        }
    +
    +                                        String parentUuid = originalFlowFile.getAttribute(CoreAttributes.UUID.key());
    +                                        attributes.put(ATTACHMENT_ORIGINAL_UUID, parentUuid);
    +                                        attributes.put(ATTACHMENT_ORIGINAL_FILENAME, originalFlowFileName);
    +
    +                                        // TODO: Extract Mime Type (HMEF doesn't seem to be able to get this info.
    +
    +                                        split = session.append(split, new OutputStreamCallback() {
    +                                            @Override
    +                                            public void process(OutputStream out) throws IOException {
    +                                                out.write(attachment.getContents());
    +                                            }
    +                                        });
    +                                        split = session.putAllAttributes(split, attributes);
    +                                        attachmentsList.add(split);
    +                                    }
    +                                } catch (FlowFileHandlingException e) {
    +                                    // Something went wrong
    +                                    // Removing splits that may have been created
    +                                    session.remove(attachmentsList);
    +                                    // Removing the original flow from its list
    +                                    originalFlowFilesList.remove(originalFlowFile);
    +                                    logger.error("Flowfile {} triggered error {} while processing message removing generated FlowFiles from sessions", new Object[]{originalFlowFile, e});
    +                                    invalidFlowFilesList.add(originalFlowFile);
    +                                }
    +                            }
    +                        }
    +                    }catch (Exception e) {
    +                        // Another error hit...
    +                        // Removing the original flow from its list
    +                        originalFlowFilesList.remove(originalFlowFile);
    +                        logger.error("Could not parse the flowfile {} as an email, treating as failure", new Object[]{originalFlowFile, e});
    +                        // Message is invalid or triggered an error during parsing
    +                        invalidFlowFilesList.add(originalFlowFile);
    +                    }
    +                }
    +        });
    +
    +        session.transfer(attachmentsList, REL_ATTACHMENTS);
    +
    +        // As per above code, originalFlowfile may be routed to invalid or
    +        // original depending on RFC2822 compliance.
    +        session.transfer(invalidFlowFilesList, REL_FAILURE);
    +        session.transfer(originalFlowFilesList, REL_ORIGINAL);
    +
    +        if (attachmentsList.size() > 10) {
    +            logger.info("Split {} into {} files", new Object[]{originalFlowFile, attachmentsList.size()});
    +        } else if (attachmentsList.size() > 1){
    +            logger.info("Split {} into {} files: {}", new Object[]{originalFlowFile, attachmentsList.size(), attachmentsList});
    +        }
    --- End diff --
    
    It is based on SplitContent
    
    https://github.com/apache/nifi/blob/1bd2cf0d09a7111bcecffd0f473aa71c25a69845/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/SplitContent.java#L292
    
    But I agree the code is hard to grasp as there are two completely separate tests occurring within the same if then else statement. 
    
    Addressed.
    



---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by olegz <gi...@git.apache.org>.
Github user olegz commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @trixpan 
    Thank you and I will definitely take a look. Also, FWIW I see already that it has some merge conflicts so you may want to look and fix those.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by olegz <gi...@git.apache.org>.
Github user olegz commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @trixpan sorry for the hold up. Actually I would like for @joewitt to look at License/Notice (as you have suggested earlier) as I don't feel competent enough as there are some things I've not seen before. @joewitt could you please just give it a quick look to make sure everything is kosher with License/Notice?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi pull request #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by asfgit <gi...@git.apache.org>.
Github user asfgit closed the pull request at:

    https://github.com/apache/nifi/pull/817


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] nifi issue #817: NIFI-2380 - Introduce ExtractTNEFAttachments

Posted by trixpan <gi...@git.apache.org>.
Github user trixpan commented on the issue:

    https://github.com/apache/nifi/pull/817
  
    @joewitt - 3rd party test files have been replaced with new files containing only NiFi & MiNiFi logos


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---