Any way to include Java Mail into my plugin?

Hello.
Im trying to make a plugin, that can send emails!
For this Im using Java Mail, v1.6.0, with implementation by sun.
It works fine everywhere (from IDEA, from compiled .jar with main method, etc.), excluding… Sponge!
If I adding Mail Api implementation to my plugin as .jar I am getting java.lang.NoClassDefFoundError: javax/mail/Authenticator.
If I adding extracted Mail Api implementation (exactly same as I doing this for other .jars, which works fine when I run it with java -jar myjar.jar), I getting java.lang.NoClassDefFoundError: com/sun/mail/util/MailLogger
From some guy from Sponge`s discord I hear that: AFAIK the sun packages don't work at all for sponge/mc (No idea why):frowning:
Is there any way how I can use Mail Api from my Sponge plugin?

Can you show your project / build scripts?

What exactly do I need to show?

I compiling plugin using default IDEA compile button…
In my maven I have this:

        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>LATEST</version>
        </dependency>

All needed files (like com.sun.mail.util.MailLogger included in my plugin .jar, but plugin does not see it, when it run by Sponge.
When I add main method to my plugin, and send email in main method, which runned by java -jar myplugin.jar - all works correct. But when it launched by Sponge - ClassNotFound

One guy from Developers discord (@Dysche (thanks him very very much!)),
sends me that code:

public class CustomClassLoader {
    private static final Class<?>[] parameters = new Class[] {
            URL.class
    };

    public static void addFile(String path) throws IOException {
        addFile(new File(path));
    }

    public static void addFile(File file) throws IOException {
        addURL(file.toURI().toURL());
    }

    @SuppressWarnings("unchecked")
    public static void addURL(URL url) throws IOException {
        Object sysloader = null;

        try {
            sysloader = Class.forName("net.minecraft.launchwrapper.Launch").getDeclaredField("classLoader").get(null);

            Field setField = sysloader.getClass().getDeclaredField("classLoaderExceptions");
            setField.setAccessible(true);

            Set<String> set = (Set<String>) setField.get(sysloader);

            if (set.contains("sun.")) {
                set.remove("sun.");
                set.remove("com.sun.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        try {
            Method method = URLClassLoader.class.getDeclaredMethod("addURL", parameters);
            method.setAccessible(true);
            method.invoke(sysloader, new Object[] {
                    url
            });
        } catch (Throwable t) {
            t.printStackTrace();
            throw new IOException("Could not add URL to system ClassLoader.");
        }
    }
}

So, I need add my Mail Api to libs folder, and call this code from preInit:

        try {
            CustomClassLoader.addFile("libs/javax.mail-1.6.0.jar");
            logger.info("Mail library successfully loaded!");
        } catch (Exception e) {
            logger.info("Mail library load failed!", e);
        }

Its works now! But why I need to do this hard manipulation? Why I cant simply add library to my plugin and use it, like with any other program?..

I don’t know what I’m talking about in this case, but I suspect it’s a safety / sanity check by forge/Mixins to make sure people arn’t doing asm modding on internal java classes. This is clearly an exception where it hurts a lot more then it helps.

1 Like

Relocate the package with the gradle shadow plugin.

2 Likes